@tradecanvas/chart 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -1
- package/dist/Chart.d.ts +10 -0
- package/dist/Chart.d.ts.map +1 -1
- package/dist/DragDropImporter-CBeJgd9y.cjs +2 -0
- package/dist/DragDropImporter-CBeJgd9y.cjs.map +1 -0
- package/dist/{DragDropImporter-C4x09P7e.js → DragDropImporter-D_WpWB5H.js} +25 -4
- package/dist/DragDropImporter-D_WpWB5H.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/widget/index.cjs +1 -1
- package/dist/widget/index.cjs.map +1 -1
- package/dist/widget/index.js +1 -1
- package/dist/widget/index.js.map +1 -1
- package/package.json +3 -3
- package/dist/DragDropImporter-C4x09P7e.js.map +0 -1
- package/dist/DragDropImporter-DeXlngof.cjs +0 -2
- package/dist/DragDropImporter-DeXlngof.cjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":[],"sources":["../../src/io/resampleOHLCV.ts","../../src/widget/widgetConfig.ts","../../src/widget/WidgetStyles.ts","../../src/widget/icons.ts","../../src/widget/WidgetDropdown.ts","../../src/widget/WidgetToolbar.ts","../../src/widget/WidgetDrawingSidebar.ts","../../src/widget/WidgetSettings.ts","../../src/widget/WidgetStatusBar.ts","../../src/widget/WidgetCommandPalette.ts","../../src/widget/WidgetSymbolSearch.ts","../../src/widget/WidgetHotkeySheet.ts","../../src/widget/WidgetReplayBar.ts","../../src/widget/WidgetWatchlist.ts","../../src/widget/WidgetAlertsPanel.ts","../../src/widget/WidgetObjectTree.ts","../../src/widget/WidgetIndicatorSettings.ts","../../src/widget/DrawingTemplateStore.ts","../../src/widget/WidgetDrawingStyle.ts","../../src/widget/DrawingFavoritesStore.ts","../../src/widget/WidgetBracketBar.ts","../../src/widget/AlertNotifier.ts","../../src/widget/ladderRows.ts","../../src/widget/WidgetDepthLadder.ts","../../src/widget/WidgetDataWindow.ts","../../src/widget/widgetShareState.ts","../../src/widget/ChartWidget.ts"],"sourcesContent":["import type { DataSeries, OHLCBar, TimeFrame } from '@tradecanvas/commons';\nimport { timeframeToMs, timeframeBucketStart } from '@tradecanvas/commons';\n\nexport interface ResampleOptions {\n /** 0 = Sunday, 1 = Monday (default) — anchor for weekly buckets. */\n weekStartsOn?: 0 | 1;\n}\n\n/**\n * Aggregate a finer OHLCV series into a coarser timeframe.\n *\n * Bars are grouped by calendar-aware bucket (see `timeframeBucketStart`):\n * open = first bar's open, high/low = extremes, close = last bar's close,\n * volume = sum. Input bars are assumed sorted ascending by `time` and are\n * never mutated.\n *\n * Upsampling (target finer than source) cannot synthesize data — pass a target\n * coarser than the source. Use `inferTimeframeMs` to detect the source spacing.\n */\nexport function resampleOHLCV(\n bars: DataSeries,\n target: TimeFrame,\n opts: ResampleOptions = {},\n): DataSeries {\n if (bars.length === 0) return [];\n const weekStartsOn = opts.weekStartsOn ?? 1;\n\n const out: OHLCBar[] = [];\n let current: OHLCBar | null = null;\n let currentKey = Number.NaN;\n\n for (const bar of bars) {\n const key = timeframeBucketStart(bar.time, target, weekStartsOn);\n if (current === null || key !== currentKey) {\n if (current !== null) out.push(current);\n current = {\n time: key,\n open: bar.open,\n high: bar.high,\n low: bar.low,\n close: bar.close,\n volume: bar.volume,\n };\n currentKey = key;\n } else {\n current = {\n time: current.time,\n open: current.open,\n high: Math.max(current.high, bar.high),\n low: Math.min(current.low, bar.low),\n close: bar.close,\n volume: current.volume + bar.volume,\n };\n }\n }\n if (current !== null) out.push(current);\n return out;\n}\n\n/**\n * Estimate the source bar spacing in milliseconds from the median gap between\n * consecutive bars. Robust to occasional gaps (weekends, halts). Returns 0 for\n * series with fewer than two bars.\n */\nexport function inferTimeframeMs(bars: DataSeries): number {\n if (bars.length < 2) return 0;\n const gaps: number[] = [];\n for (let i = 1; i < bars.length; i++) {\n const gap = bars[i].time - bars[i - 1].time;\n if (gap > 0) gaps.push(gap);\n }\n if (gaps.length === 0) return 0;\n gaps.sort((a, b) => a - b);\n return gaps[Math.floor(gaps.length / 2)];\n}\n\n/**\n * Whether `target` is coarser than (or equal to) the source spacing, i.e. a\n * valid downsample. A non-positive `sourceMs` (unknown) is treated as valid.\n */\nexport function canResample(sourceMs: number, target: TimeFrame): boolean {\n if (sourceMs <= 0) return true;\n return timeframeToMs(target) >= sourceMs;\n}\n","import type { ChartType, DrawingToolType, TimeFrame } from '@tradecanvas/commons';\nimport type { IndicatorDef, DrawingToolGroupDef, ChartSettingsState } from './types.js';\n\nexport const TIMEFRAMES: { label: string; value: TimeFrame }[] = [\n { label: '1m', value: '1m' },\n { label: '5m', value: '5m' },\n { label: '15m', value: '15m' },\n { label: '1H', value: '1h' },\n { label: '4H', value: '4h' },\n { label: '1D', value: '1d' },\n];\n\nexport const CHART_TYPES: { label: string; value: ChartType }[] = [\n { label: 'Candlestick', value: 'candlestick' },\n { label: 'Line', value: 'line' },\n { label: 'Area', value: 'area' },\n { label: 'Bar', value: 'bar' },\n { label: 'Heikin-Ashi', value: 'heikinAshi' },\n { label: 'Hollow Candle', value: 'hollowCandle' },\n { label: 'Baseline', value: 'baseline' },\n { label: 'Volume Candles', value: 'volumeCandles' },\n { label: 'Equivolume', value: 'equivolume' },\n { label: 'HLC Area', value: 'hlcArea' },\n { label: 'Step Line', value: 'stepLine' },\n { label: 'Line + Markers', value: 'lineWithMarkers' },\n];\n\nexport const DRAWING_TOOL_GROUPS: DrawingToolGroupDef[] = [\n {\n label: 'Lines',\n tools: [\n { label: 'Trend Line', value: 'trendLine' as DrawingToolType },\n { label: 'Ray', value: 'ray' as DrawingToolType },\n { label: 'Extended Line', value: 'extendedLine' as DrawingToolType },\n ],\n },\n {\n label: 'Horizontal/Vertical',\n tools: [\n { label: 'Horizontal Line', value: 'horizontalLine' as DrawingToolType },\n { label: 'Vertical Line', value: 'verticalLine' as DrawingToolType },\n ],\n },\n {\n label: 'Channels',\n tools: [\n { label: 'Parallel Channel', value: 'parallelChannel' as DrawingToolType },\n { label: 'Regression Channel', value: 'regressionChannel' as DrawingToolType },\n ],\n },\n {\n label: 'Fibonacci',\n tools: [\n { label: 'Fib Retracement', value: 'fibRetracement' as DrawingToolType },\n { label: 'Fib Extension', value: 'fibExtension' as DrawingToolType },\n ],\n },\n {\n label: 'Shapes',\n tools: [\n { label: 'Rectangle', value: 'rectangle' as DrawingToolType },\n { label: 'Ellipse', value: 'ellipse' as DrawingToolType },\n { label: 'Triangle', value: 'triangle' as DrawingToolType },\n ],\n },\n {\n label: 'Gann & Advanced',\n tools: [\n { label: 'Pitchfork', value: 'pitchfork' as DrawingToolType },\n { label: 'Gann Fan', value: 'gannFan' as DrawingToolType },\n { label: 'Gann Box', value: 'gannBox' as DrawingToolType },\n { label: 'Elliott Wave', value: 'elliottWave' as DrawingToolType },\n ],\n },\n {\n label: 'Measure',\n tools: [\n { label: 'Price Range', value: 'priceRange' as DrawingToolType },\n { label: 'Date Range', value: 'dateRange' as DrawingToolType },\n { label: 'Measure', value: 'measure' as DrawingToolType },\n ],\n },\n {\n label: 'Annotation',\n tools: [\n { label: 'Text', value: 'text' as DrawingToolType },\n { label: 'Arrow', value: 'arrow' as DrawingToolType },\n ],\n },\n];\n\nexport const INDICATORS: IndicatorDef[] = [\n { id: 'sma', name: 'SMA', type: 'overlay' },\n { id: 'ema', name: 'EMA', type: 'overlay' },\n { id: 'hma', name: 'Hull MA', type: 'overlay' },\n { id: 'mtfma', name: 'MTF Moving Average', type: 'overlay' },\n { id: 'bb', name: 'Bollinger Bands', type: 'overlay' },\n { id: 'vwap', name: 'VWAP', type: 'overlay' },\n { id: 'avwap', name: 'Anchored VWAP', type: 'overlay' },\n { id: 'svwap', name: 'Session VWAP', type: 'overlay' },\n { id: 'ichimoku', name: 'Ichimoku Cloud', type: 'overlay' },\n { id: 'psar', name: 'Parabolic SAR', type: 'overlay' },\n { id: 'supertrend', name: 'Supertrend', type: 'overlay' },\n { id: 'keltner', name: 'Keltner Channel', type: 'overlay' },\n { id: 'donchian', name: 'Donchian Channel', type: 'overlay' },\n { id: 'pivots', name: 'Pivot Points', type: 'overlay' },\n { id: 'zigzag', name: 'ZigZag', type: 'overlay' },\n { id: 'lrc', name: 'Linear Regression Channel', type: 'overlay' },\n { id: 'chandelier', name: 'Chandelier Exit', type: 'overlay' },\n { id: 'alligator', name: 'Alligator', type: 'overlay' },\n { id: 'rsi', name: 'RSI', type: 'panel' },\n { id: 'macd', name: 'MACD', type: 'panel' },\n { id: 'stochastic', name: 'Stochastic', type: 'panel' },\n { id: 'atr', name: 'ATR', type: 'panel' },\n { id: 'adx', name: 'ADX', type: 'panel' },\n { id: 'obv', name: 'OBV', type: 'panel' },\n { id: 'williamsR', name: 'Williams %R', type: 'panel' },\n { id: 'cci', name: 'CCI', type: 'panel' },\n { id: 'mfi', name: 'MFI', type: 'panel' },\n { id: 'roc', name: 'ROC', type: 'panel' },\n { id: 'tsi', name: 'TSI', type: 'panel' },\n { id: 'cmf', name: 'CMF', type: 'panel' },\n { id: 'aroon', name: 'Aroon', type: 'panel' },\n { id: 'stddev', name: 'Std Deviation', type: 'panel' },\n { id: 'vroc', name: 'Volume ROC', type: 'panel' },\n { id: 'ad', name: 'Acc/Dist', type: 'panel' },\n { id: 'ao', name: 'Awesome Oscillator', type: 'panel' },\n { id: 'chaikinOsc', name: 'Chaikin Oscillator', type: 'panel' },\n { id: 'voldelta', name: 'Volume Delta', type: 'panel' },\n { id: 'vortex', name: 'Vortex Indicator', type: 'panel' },\n { id: 'chop', name: 'Choppiness Index', type: 'panel' },\n { id: 'uo', name: 'Ultimate Oscillator', type: 'panel' },\n { id: 'fi', name: 'Force Index', type: 'panel' },\n { id: 'crsi', name: 'Connors RSI', type: 'panel' },\n { id: 'coppock', name: 'Coppock Curve', type: 'panel' },\n { id: 'kst', name: 'Know Sure Thing', type: 'panel' },\n { id: 'elderray', name: 'Elder Ray', type: 'panel' },\n { id: 'stc', name: 'Schaff Trend Cycle', type: 'panel' },\n { id: 'kvo', name: 'Klinger Oscillator', type: 'panel' },\n { id: 'fisher', name: 'Fisher Transform', type: 'panel' },\n { id: 'dpo', name: 'Detrended Price Osc', type: 'panel' },\n { id: 'bop', name: 'Balance of Power', type: 'panel' },\n { id: 'massindex', name: 'Mass Index', type: 'panel' },\n { id: 'cmo', name: 'Chande Momentum', type: 'panel' },\n { id: 'trix', name: 'TRIX', type: 'panel' },\n { id: 'emv', name: 'Ease of Movement', type: 'panel' },\n { id: 'pvt', name: 'Price Volume Trend', type: 'panel' },\n { id: 'wad', name: 'Williams A/D', type: 'panel' },\n { id: 'chaikinvol', name: 'Chaikin Volatility', type: 'panel' },\n { id: 'rvi', name: 'Relative Vigor Index', type: 'panel' },\n { id: 'stochrsi', name: 'Stochastic RSI', type: 'panel' },\n { id: 'ppo', name: 'Percentage Price Oscillator', type: 'panel' },\n { id: 'ac', name: 'Accelerator Oscillator', type: 'panel' },\n { id: 'rmi', name: 'Relative Momentum Index', type: 'panel' },\n { id: 'disparity', name: 'Disparity Index', type: 'panel' },\n { id: 'qstick', name: 'Qstick', type: 'panel' },\n { id: 'pgo', name: 'Pretty Good Oscillator', type: 'panel' },\n { id: 'volumeProfile', name: 'Volume Profile', type: 'panel' },\n];\n\nexport const POPULAR_INDICATORS = [\n 'sma', 'ema', 'bb', 'rsi', 'macd', 'stochastic',\n 'vwap', 'atr', 'obv', 'ichimoku',\n];\n\nexport const DEFAULT_SYMBOLS = [\n 'BTCUSDT', 'ETHUSDT', 'SOLUSDT', 'BNBUSDT',\n];\n\nexport const DEFAULT_SETTINGS: ChartSettingsState = {\n candleUpColor: '#26A69A',\n candleDownColor: '#EF5350',\n candleUpWick: '#26A69A',\n candleDownWick: '#EF5350',\n backgroundColor: '#131722',\n gridColor: '#1E222D',\n gridVisible: true,\n volumeVisible: true,\n volumeProfileVisible: false,\n marketProfileVisible: false,\n marketProfileSplit: false,\n marketProfileLetters: false,\n marketProfileBuckets: 48,\n marketProfileOpacity: 0.32,\n depthHeatmapVisible: false,\n depthHeatmapOpacity: 0.7,\n sessionShadingVisible: false,\n pivotMarkersVisible: false,\n pivotStrength: 5,\n pivotStructureLabels: false,\n periodLevelsVisible: false,\n periodLevelsPeriod: 'day',\n legendVisible: true,\n barCountdown: true,\n logScale: false,\n scaleMode: 'regular',\n autoScale: true,\n crosshairMode: 'magnet',\n numberLocale: 'en-US',\n timezone: 'local',\n};\n","import widgetCss from './WidgetStyles.css?raw';\r\n\r\nlet refCount = 0;\r\nconst STYLE_ID = 'tcw-styles';\r\n\r\n/**\r\n * Inject the widget stylesheet into `document.head`. Reference-counted so\r\n * multiple `ChartWidget` instances share the same `<style>` tag and the last\r\n * to detach removes it. CSS lives in a sibling `.css` file and is inlined at\r\n * build time via Vite's `?raw` query — consumers see a plain string at runtime.\r\n */\r\nexport function injectWidgetStyles(): void {\r\n refCount++;\r\n if (refCount > 1) return;\r\n if (document.getElementById(STYLE_ID)) return;\r\n\r\n const style = document.createElement('style');\r\n style.id = STYLE_ID;\r\n style.textContent = widgetCss;\r\n document.head.appendChild(style);\r\n}\r\n\r\nexport function removeWidgetStyles(): void {\r\n refCount--;\r\n if (refCount > 0) return;\r\n\r\n const style = document.getElementById(STYLE_ID);\r\n if (style) {\r\n style.remove();\r\n }\r\n}\r\n","const ICON_PATHS: Record<string, string> = {\n cursor: '<path d=\"M3 3l7.07 16.97 2.51-7.39 7.39-2.51L3 3z\"/><path d=\"M13 13l6 6\"/>',\n trendingUp: '<polyline points=\"22 7 13.5 15.5 8.5 10.5 2 17\"/><polyline points=\"16 7 22 7 22 13\"/>',\n minus: '<path d=\"M5 12h14\"/>',\n penLine: '<path d=\"M12 20h9\"/><path d=\"M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z\"/>',\n hash: '<line x1=\"4\" y1=\"9\" x2=\"20\" y2=\"9\"/><line x1=\"4\" y1=\"15\" x2=\"20\" y2=\"15\"/><line x1=\"10\" y1=\"3\" x2=\"8\" y2=\"21\"/><line x1=\"16\" y1=\"3\" x2=\"14\" y2=\"21\"/>',\n square: '<rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\"/>',\n gitBranch: '<line x1=\"6\" y1=\"3\" x2=\"6\" y2=\"15\"/><circle cx=\"18\" cy=\"6\" r=\"3\"/><circle cx=\"6\" cy=\"18\" r=\"3\"/><path d=\"M18 9a9 9 0 0 1-9 9\"/>',\n ruler: '<path d=\"M21.3 15.3a2.4 2.4 0 0 1 0 3.4l-2.6 2.6a2.4 2.4 0 0 1-3.4 0L2.7 8.7a2.41 2.41 0 0 1 0-3.4l2.6-2.6a2.41 2.41 0 0 1 3.4 0Z\"/><path d=\"m14.5 12.5 2-2\"/><path d=\"m11.5 9.5 2-2\"/><path d=\"m8.5 6.5 2-2\"/><path d=\"m17.5 15.5 2-2\"/>',\n type: '<polyline points=\"4 7 4 4 20 4 20 7\"/><line x1=\"9\" y1=\"20\" x2=\"15\" y2=\"20\"/><line x1=\"12\" y1=\"4\" x2=\"12\" y2=\"20\"/>',\n magnet: '<path d=\"m6 15-4-4 6.75-6.77a7.79 7.79 0 0 1 11 11L13 22l-4-4 6.39-6.36a2.14 2.14 0 0 0-3-3L6 15\"/><path d=\"m5 8 4 4\"/><path d=\"m12 15 4 4\"/>',\n undo: '<path d=\"M3 7v6h6\"/><path d=\"M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13\"/>',\n redo: '<path d=\"M21 7v6h-6\"/><path d=\"M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3L21 13\"/>',\n trash: '<path d=\"M3 6h18\"/><path d=\"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6\"/><path d=\"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2\"/><line x1=\"10\" y1=\"11\" x2=\"10\" y2=\"17\"/><line x1=\"14\" y1=\"11\" x2=\"14\" y2=\"17\"/>',\n camera: '<path d=\"M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z\"/><circle cx=\"12\" cy=\"13\" r=\"3\"/>',\n settings: '<path d=\"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/>',\n moon: '<path d=\"M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z\"/>',\n sun: '<circle cx=\"12\" cy=\"12\" r=\"4\"/><path d=\"M12 2v2\"/><path d=\"M12 20v2\"/><path d=\"m4.93 4.93 1.41 1.41\"/><path d=\"m17.66 17.66 1.41 1.41\"/><path d=\"M2 12h2\"/><path d=\"M20 12h2\"/><path d=\"m6.34 17.66-1.41 1.41\"/><path d=\"m19.07 4.93-1.41 1.41\"/>',\n chevronDown: '<path d=\"m6 9 6 6 6-6\"/>',\n chevronUp: '<path d=\"m18 15-6-6-6 6\"/>',\n barChart: '<line x1=\"12\" y1=\"20\" x2=\"12\" y2=\"10\"/><line x1=\"18\" y1=\"20\" x2=\"18\" y2=\"4\"/><line x1=\"6\" y1=\"20\" x2=\"6\" y2=\"16\"/>',\n x: '<path d=\"M18 6 6 18\"/><path d=\"m6 6 12 12\"/>',\n play: '<polygon points=\"6 3 20 12 6 21 6 3\"/>',\n pause: '<rect width=\"4\" height=\"16\" x=\"6\" y=\"4\"/><rect width=\"4\" height=\"16\" x=\"14\" y=\"4\"/>',\n stop: '<rect width=\"14\" height=\"14\" x=\"5\" y=\"5\" rx=\"1\"/>',\n receipt: '<path d=\"M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1Z\"/><path d=\"M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8\"/><path d=\"M12 17.5v-11\"/>',\n bell: '<path d=\"M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9\"/><path d=\"M10.3 21a1.94 1.94 0 0 0 3.4 0\"/>',\n plus: '<path d=\"M5 12h14\"/><path d=\"M12 5v14\"/>',\n layers: '<path d=\"m12 2 9 5-9 5-9-5 9-5Z\"/><path d=\"m3 12 9 5 9-5\"/><path d=\"m3 17 9 5 9-5\"/>',\n eye: '<path d=\"M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7Z\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/>',\n eyeOff: '<path d=\"M9.9 4.24A9.12 9.12 0 0 1 12 4c6.5 0 10 7 10 7a13.2 13.2 0 0 1-1.67 2.68\"/><path d=\"M6.6 6.6A13.06 13.06 0 0 0 2 11s3.5 7 10 7a9.1 9.1 0 0 0 5.4-1.6\"/><path d=\"m2 2 20 20\"/>',\n lock: '<rect width=\"18\" height=\"11\" x=\"3\" y=\"11\" rx=\"2\"/><path d=\"M7 11V7a5 5 0 0 1 10 0v4\"/>',\n unlock: '<rect width=\"18\" height=\"11\" x=\"3\" y=\"11\" rx=\"2\"/><path d=\"M7 11V7a5 5 0 0 1 9.9-1\"/>',\n palette: '<circle cx=\"13.5\" cy=\"6.5\" r=\".5\" fill=\"currentColor\"/><circle cx=\"17.5\" cy=\"10.5\" r=\".5\" fill=\"currentColor\"/><circle cx=\"8.5\" cy=\"7.5\" r=\".5\" fill=\"currentColor\"/><circle cx=\"6.5\" cy=\"12.5\" r=\".5\" fill=\"currentColor\"/><path d=\"M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2Z\"/>',\n trendingDown: '<polyline points=\"22 17 13.5 8.5 8.5 13.5 2 7\"/><polyline points=\"16 17 22 17 22 11\"/>',\n check: '<polyline points=\"20 6 9 17 4 12\"/>',\n ladder: '<rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/><line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"21\"/><line x1=\"3\" y1=\"8\" x2=\"21\" y2=\"8\"/><line x1=\"3\" y1=\"13\" x2=\"21\" y2=\"13\"/><line x1=\"3\" y1=\"18\" x2=\"21\" y2=\"18\"/>',\n};\n\nexport function createIcon(name: string, size = 14): string {\n const paths = ICON_PATHS[name];\n if (!paths) return '';\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${size}\" height=\"${size}\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">${paths}</svg>`;\n}\n","export class WidgetDropdown {\n private trigger: HTMLElement;\n private panel: HTMLDivElement;\n private _isOpen = false;\n private onOutsideClick: (e: MouseEvent) => void;\n private onEscapeKey: (e: KeyboardEvent) => void;\n private onTriggerClick: () => void;\n\n constructor(trigger: HTMLElement, config: { width?: string; align?: 'left' | 'right' } = {}) {\n this.trigger = trigger;\n\n this.panel = document.createElement('div');\n this.panel.className = 'tcw-dropdown';\n this.panel.style.width = config.width ?? '200px';\n if (config.align === 'right') {\n this.panel.style.right = '0';\n } else {\n this.panel.style.left = '0';\n }\n this.panel.style.display = 'none';\n\n // Position relative to trigger\n trigger.style.position = 'relative';\n trigger.appendChild(this.panel);\n\n this.onTriggerClick = () => {\n if (this._isOpen) {\n this.close();\n } else {\n this.open();\n }\n };\n\n this.onOutsideClick = (e: MouseEvent) => {\n if (!this.trigger.contains(e.target as Node)) {\n this.close();\n }\n };\n\n this.onEscapeKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n this.close();\n }\n };\n\n trigger.addEventListener('click', this.onTriggerClick);\n }\n\n setContent(html: string): void {\n this.panel.innerHTML = html;\n }\n\n open(): void {\n if (this._isOpen) return;\n this._isOpen = true;\n this.panel.style.display = '';\n document.addEventListener('mousedown', this.onOutsideClick);\n document.addEventListener('keydown', this.onEscapeKey);\n }\n\n close(): void {\n if (!this._isOpen) return;\n this._isOpen = false;\n this.panel.style.display = 'none';\n document.removeEventListener('mousedown', this.onOutsideClick);\n document.removeEventListener('keydown', this.onEscapeKey);\n }\n\n isOpen(): boolean {\n return this._isOpen;\n }\n\n destroy(): void {\n this.trigger.removeEventListener('click', this.onTriggerClick);\n document.removeEventListener('mousedown', this.onOutsideClick);\n document.removeEventListener('keydown', this.onEscapeKey);\n this.panel.remove();\n }\n}\n","import type { ChartType } from '@tradecanvas/commons';\nimport type { ToolbarConfig, ToolbarCallbacks, WidgetState, ActiveIndicator } from './types.js';\nimport { createIcon } from './icons.js';\nimport { WidgetDropdown } from './WidgetDropdown.js';\n\nexport class WidgetToolbar {\n private config: ToolbarConfig;\n private callbacks: ToolbarCallbacks;\n private el: HTMLDivElement;\n private chartTypeDropdown: WidgetDropdown | null = null;\n private indicatorDropdown: WidgetDropdown | null = null;\n private tfButtons: HTMLButtonElement[] = [];\n private chipsContainer: HTMLDivElement | null = null;\n private themeBtn: HTMLButtonElement | null = null;\n\n constructor(host: HTMLElement, config: ToolbarConfig, callbacks: ToolbarCallbacks) {\n this.config = config;\n this.callbacks = callbacks;\n this.el = document.createElement('div');\n this.el.className = 'tcw-toolbar';\n this.build();\n host.appendChild(this.el);\n }\n\n private build(): void {\n const { config, callbacks, el } = this;\n\n // Symbol button\n const symbolBtn = document.createElement('button');\n symbolBtn.className = 'tcw-toolbar-symbol';\n symbolBtn.dataset.role = 'symbol';\n symbolBtn.addEventListener('click', callbacks.onSymbolClick);\n el.appendChild(symbolBtn);\n el.appendChild(this.sep());\n\n // Timeframes\n const tfGroup = document.createElement('div');\n tfGroup.className = 'tcw-toolbar-group';\n for (const tf of config.timeframes) {\n const btn = document.createElement('button');\n btn.className = 'tcw-btn';\n btn.textContent = tf.label;\n btn.dataset.tf = tf.value;\n btn.addEventListener('click', () => callbacks.onTimeframe(tf.value));\n tfGroup.appendChild(btn);\n this.tfButtons.push(btn);\n }\n el.appendChild(tfGroup);\n el.appendChild(this.sep());\n\n // Chart type dropdown\n const ctWrap = document.createElement('div');\n ctWrap.style.position = 'relative';\n ctWrap.style.display = 'inline-flex';\n\n const ctTrigger = document.createElement('button');\n ctTrigger.className = 'tcw-dropdown-trigger';\n ctTrigger.dataset.role = 'charttype';\n ctWrap.appendChild(ctTrigger);\n el.appendChild(ctWrap);\n\n this.chartTypeDropdown = new WidgetDropdown(ctWrap, { width: '160px' });\n this.buildChartTypeMenu();\n\n el.appendChild(this.sep());\n\n // Indicators dropdown\n const indWrap = document.createElement('div');\n indWrap.style.position = 'relative';\n indWrap.style.display = 'inline-flex';\n\n const indTrigger = document.createElement('button');\n indTrigger.className = 'tcw-dropdown-trigger';\n indTrigger.dataset.role = 'indicators';\n indWrap.appendChild(indTrigger);\n el.appendChild(indWrap);\n\n this.indicatorDropdown = new WidgetDropdown(indWrap, { width: '280px' });\n this.buildIndicatorMenu();\n\n // Indicator chips\n this.chipsContainer = document.createElement('div');\n this.chipsContainer.className = 'tcw-indicator-chips';\n el.appendChild(this.chipsContainer);\n\n // Spacer\n el.appendChild(this.spacer());\n\n // Right side buttons\n if (callbacks.onToggleReplay) {\n const replayBtn = this.iconBtn('play', 'Bar replay', callbacks.onToggleReplay);\n replayBtn.dataset.role = 'replay';\n el.appendChild(replayBtn);\n }\n\n if (callbacks.onBracket) {\n const onBracket = callbacks.onBracket;\n const longBtn = this.iconBtn('trendingUp', 'Long bracket', () => onBracket('buy'));\n longBtn.dataset.role = 'long';\n longBtn.classList.add('tcw-btn-long');\n el.appendChild(longBtn);\n const shortBtn = this.iconBtn('trendingDown', 'Short bracket', () => onBracket('sell'));\n shortBtn.dataset.role = 'short';\n shortBtn.classList.add('tcw-btn-short');\n el.appendChild(shortBtn);\n }\n\n if (callbacks.onToggleLadder) {\n const ladderBtn = this.iconBtn('ladder', 'Depth ladder', callbacks.onToggleLadder);\n ladderBtn.dataset.role = 'ladder';\n el.appendChild(ladderBtn);\n }\n\n if (callbacks.onToggleObjects) {\n const objectsBtn = this.iconBtn('layers', 'Objects', callbacks.onToggleObjects);\n objectsBtn.dataset.role = 'objects';\n el.appendChild(objectsBtn);\n }\n\n if (callbacks.onToggleAlerts) {\n const alertsBtn = this.iconBtn('bell', 'Price alerts', callbacks.onToggleAlerts);\n alertsBtn.dataset.role = 'alerts';\n el.appendChild(alertsBtn);\n }\n\n const screenshotBtn = this.iconBtn('camera', 'Screenshot', callbacks.onScreenshot);\n el.appendChild(screenshotBtn);\n\n const settingsBtn = this.iconBtn('settings', 'Chart Settings', callbacks.onSettings);\n el.appendChild(settingsBtn);\n\n this.themeBtn = this.iconBtn('moon', 'Toggle theme', callbacks.onToggleTheme);\n this.themeBtn.dataset.role = 'theme';\n el.appendChild(this.themeBtn);\n }\n\n private buildChartTypeMenu(): void {\n if (!this.chartTypeDropdown) return;\n const items = this.config.chartTypes.map(ct =>\n `<button class=\"tcw-dropdown-item\" data-ct=\"${ct.value}\">${ct.label}</button>`\n ).join('');\n this.chartTypeDropdown.setContent(items);\n\n // Attach events to items after content set\n const panel = this.chartTypeDropdown['panel'] as HTMLDivElement;\n panel.querySelectorAll('.tcw-dropdown-item').forEach((btn) => {\n btn.addEventListener('click', (e) => {\n const value = (e.currentTarget as HTMLElement).dataset.ct as ChartType;\n this.callbacks.onChartType(value);\n this.chartTypeDropdown?.close();\n });\n });\n }\n\n private buildIndicatorMenu(): void {\n if (!this.indicatorDropdown) return;\n const { indicators, popularIndicatorIds } = this.config;\n\n const popular = indicators.filter(d => popularIndicatorIds.includes(d.id));\n const other = indicators.filter(d => !popularIndicatorIds.includes(d.id));\n\n let html = '<div class=\"tcw-dropdown-label\">Popular</div>';\n for (const ind of popular) {\n html += `<button class=\"tcw-dropdown-item\" data-ind=\"${ind.id}\"><span>${ind.name}</span><span class=\"tcw-tag\">${ind.type}</span></button>`;\n }\n html += '<div class=\"tcw-dropdown-divider\"></div>';\n html += '<div class=\"tcw-dropdown-label\">All</div>';\n for (const ind of other) {\n html += `<button class=\"tcw-dropdown-item\" data-ind=\"${ind.id}\"><span>${ind.name}</span><span class=\"tcw-tag\">${ind.type}</span></button>`;\n }\n\n this.indicatorDropdown.setContent(html);\n\n const panel = this.indicatorDropdown['panel'] as HTMLDivElement;\n panel.querySelectorAll('.tcw-dropdown-item[data-ind]').forEach((btn) => {\n btn.addEventListener('click', (e) => {\n const id = (e.currentTarget as HTMLElement).dataset.ind!;\n this.callbacks.onAddIndicator(id);\n });\n });\n }\n\n update(state: WidgetState): void {\n // Symbol\n const symbolBtn = this.el.querySelector('[data-role=\"symbol\"]') as HTMLButtonElement | null;\n if (symbolBtn) symbolBtn.textContent = state.symbol;\n\n // Timeframe buttons\n for (const btn of this.tfButtons) {\n btn.classList.toggle('tcw-active', btn.dataset.tf === state.timeframe);\n }\n\n // Chart type trigger label\n const ctTrigger = this.el.querySelector('[data-role=\"charttype\"]') as HTMLElement | null;\n if (ctTrigger) {\n const label = this.config.chartTypes.find(t => t.value === state.chartType)?.label ?? 'Candles';\n ctTrigger.innerHTML = `${createIcon('barChart', 14)} ${label} ${createIcon('chevronDown', 12)}`;\n }\n\n // Indicator trigger + badge\n const indTrigger = this.el.querySelector('[data-role=\"indicators\"]') as HTMLElement | null;\n if (indTrigger) {\n const count = state.activeIndicators.size;\n let inner = `${createIcon('trendingUp', 14)} Indicators`;\n if (count > 0) {\n inner += ` <span class=\"tcw-badge-count\">${count}</span>`;\n }\n indTrigger.innerHTML = inner;\n }\n\n // Chips\n if (this.chipsContainer) {\n const activeList = this.getActiveIndicatorList(state);\n this.chipsContainer.innerHTML = '';\n for (const ind of activeList) {\n const chip = document.createElement('div');\n chip.className = 'tcw-indicator-chip';\n\n const label = document.createElement('span');\n label.textContent = ind.label;\n chip.appendChild(label);\n\n const removeBtn = document.createElement('button');\n removeBtn.className = 'tcw-chip-remove';\n removeBtn.innerHTML = createIcon('x', 10);\n removeBtn.addEventListener('click', () => this.callbacks.onRemoveIndicator(ind.instanceId));\n chip.appendChild(removeBtn);\n\n this.chipsContainer.appendChild(chip);\n }\n }\n\n // Theme toggle icon\n if (this.themeBtn) {\n this.themeBtn.innerHTML = state.isDark ? createIcon('moon', 14) : createIcon('sun', 14);\n }\n }\n\n private getActiveIndicatorList(state: WidgetState): ActiveIndicator[] {\n const result: ActiveIndicator[] = [];\n for (const [id, instanceId] of state.activeIndicators.entries()) {\n result.push({ instanceId, id, label: id.toUpperCase() });\n }\n return result;\n }\n\n private sep(): HTMLSpanElement {\n const s = document.createElement('span');\n s.className = 'tcw-toolbar-sep';\n return s;\n }\n\n private spacer(): HTMLSpanElement {\n const s = document.createElement('span');\n s.className = 'tcw-toolbar-spacer';\n return s;\n }\n\n private iconBtn(icon: string, title: string, onClick: () => void): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.className = 'tcw-btn-icon';\n btn.title = title;\n btn.innerHTML = createIcon(icon, 14);\n btn.addEventListener('click', onClick);\n return btn;\n }\n\n destroy(): void {\n this.chartTypeDropdown?.destroy();\n this.indicatorDropdown?.destroy();\n this.el.remove();\n }\n}\n","import type { SidebarConfig, SidebarCallbacks, WidgetState } from './types.js';\nimport { createIcon } from './icons.js';\n\nconst GROUP_ICONS = [\n 'trendingUp', 'minus', 'penLine', 'hash', 'square', 'gitBranch', 'ruler', 'type',\n];\n\n/** Icon for a drawing tool in the favorites strip — falls back to a pen. */\nconst TOOL_ICONS: Record<string, string> = {\n trendLine: 'trendingUp', ray: 'trendingUp', extendedLine: 'trendingUp',\n horizontalLine: 'minus', verticalLine: 'penLine',\n rectangle: 'square', ellipse: 'square', triangle: 'square', arrow: 'trendingUp',\n parallelChannel: 'gitBranch', regressionChannel: 'gitBranch', pitchfork: 'gitBranch',\n fibRetracement: 'hash', fibExtension: 'hash', fibTimeZones: 'hash',\n gannBox: 'hash', gannFan: 'gitBranch', elliottWave: 'trendingUp',\n priceRange: 'ruler', dateRange: 'ruler', measure: 'ruler',\n textAnnotation: 'type', anchoredVWAP: 'trendingUp', volumeProfileRange: 'barChart',\n};\n\nfunction toolIcon(tool: string): string {\n return TOOL_ICONS[tool] ?? 'penLine';\n}\n\n/** Human label for a tool id, sourced from the configured groups. */\nfunction toolLabel(groups: SidebarConfig['drawingToolGroups'], tool: string): string {\n for (const g of groups) {\n const t = g.tools.find((x) => x.value === tool);\n if (t) return t.label;\n }\n return tool;\n}\n\nexport class WidgetDrawingSidebar {\n private config: SidebarConfig;\n private callbacks: SidebarCallbacks;\n private el: HTMLDivElement;\n private groupWraps: HTMLDivElement[] = [];\n private groupButtons: HTMLButtonElement[] = [];\n private cursorBtn: HTMLButtonElement | null = null;\n private magnetBtn: HTMLButtonElement | null = null;\n private flyoutEl: HTMLDivElement | null = null;\n private favoritesEl: HTMLDivElement | null = null;\n private favoritesDivider: HTMLDivElement | null = null;\n private favorites: string[] = [];\n\n constructor(host: HTMLElement, config: SidebarConfig, callbacks: SidebarCallbacks) {\n this.config = config;\n this.callbacks = callbacks;\n this.el = document.createElement('div');\n this.el.className = 'tcw-sidebar';\n this.build();\n host.appendChild(this.el);\n }\n\n private build(): void {\n const { config, callbacks, el } = this;\n\n // Cursor button\n this.cursorBtn = document.createElement('button');\n this.cursorBtn.className = 'tcw-sidebar-btn';\n this.cursorBtn.title = 'Cursor';\n this.cursorBtn.innerHTML = createIcon('cursor', 14);\n this.cursorBtn.addEventListener('click', callbacks.onCancelDrawing);\n el.appendChild(this.cursorBtn);\n\n el.appendChild(this.divider());\n\n // Favorites strip (pinned tools) — only when favorites are enabled.\n if (callbacks.onToggleFavorite) {\n this.favorites = [...(config.favorites ?? [])];\n this.favoritesEl = document.createElement('div');\n this.favoritesEl.className = 'tcw-sidebar-favorites';\n el.appendChild(this.favoritesEl);\n this.favoritesDivider = this.divider();\n el.appendChild(this.favoritesDivider);\n this.renderFavorites();\n }\n\n // Tool groups\n config.drawingToolGroups.forEach((group, idx) => {\n const wrap = document.createElement('div');\n wrap.className = 'tcw-tool-group-wrap';\n\n const btn = document.createElement('button');\n btn.className = 'tcw-sidebar-btn';\n btn.title = group.label;\n btn.innerHTML = createIcon(GROUP_ICONS[idx] ?? 'square', 14);\n\n if (group.tools.length > 1) {\n const dot = document.createElement('span');\n dot.className = 'tcw-multi-dot';\n btn.appendChild(dot);\n }\n\n btn.addEventListener('click', () => callbacks.onDrawingTool(group.tools[0].value));\n wrap.appendChild(btn);\n\n // Flyout events via JS (not CSS hover)\n wrap.addEventListener('mouseenter', () => this.showFlyout(idx));\n wrap.addEventListener('mouseleave', () => this.hideFlyout());\n\n el.appendChild(wrap);\n this.groupWraps.push(wrap);\n this.groupButtons.push(btn);\n });\n\n // Spacer\n const spacer = document.createElement('div');\n spacer.className = 'tcw-sidebar-spacer';\n el.appendChild(spacer);\n\n el.appendChild(this.divider());\n\n // Bottom tools\n if (callbacks.onToggleStyle) {\n const styleBtn = document.createElement('button');\n styleBtn.className = 'tcw-sidebar-btn';\n styleBtn.title = 'Drawing style & templates';\n styleBtn.dataset.role = 'style';\n styleBtn.innerHTML = createIcon('palette', 14);\n styleBtn.addEventListener('click', callbacks.onToggleStyle);\n el.appendChild(styleBtn);\n }\n\n this.magnetBtn = document.createElement('button');\n this.magnetBtn.className = 'tcw-sidebar-btn';\n this.magnetBtn.title = 'Magnet';\n this.magnetBtn.innerHTML = createIcon('magnet', 14);\n this.magnetBtn.addEventListener('click', callbacks.onToggleMagnet);\n el.appendChild(this.magnetBtn);\n\n const undoBtn = document.createElement('button');\n undoBtn.className = 'tcw-sidebar-btn';\n undoBtn.title = 'Undo';\n undoBtn.innerHTML = createIcon('undo', 14);\n undoBtn.addEventListener('click', callbacks.onUndo);\n el.appendChild(undoBtn);\n\n const redoBtn = document.createElement('button');\n redoBtn.className = 'tcw-sidebar-btn';\n redoBtn.title = 'Redo';\n redoBtn.innerHTML = createIcon('redo', 14);\n redoBtn.addEventListener('click', callbacks.onRedo);\n el.appendChild(redoBtn);\n\n const clearBtn = document.createElement('button');\n clearBtn.className = 'tcw-sidebar-btn tcw-danger';\n clearBtn.title = 'Clear all';\n clearBtn.innerHTML = createIcon('trash', 14);\n clearBtn.addEventListener('click', callbacks.onClearDrawings);\n el.appendChild(clearBtn);\n }\n\n /** Update the pinned-tools strip. */\n setFavorites(favorites: string[]): void {\n this.favorites = [...favorites];\n this.renderFavorites();\n }\n\n private renderFavorites(): void {\n if (!this.favoritesEl) return;\n this.favoritesEl.replaceChildren();\n const visible = this.favorites.length > 0;\n this.favoritesEl.style.display = visible ? '' : 'none';\n if (this.favoritesDivider) this.favoritesDivider.style.display = visible ? '' : 'none';\n\n for (const tool of this.favorites) {\n const btn = document.createElement('button');\n btn.className = 'tcw-sidebar-btn';\n btn.title = `${toolLabel(this.config.drawingToolGroups, tool)} (right-click to unpin)`;\n btn.dataset.toolValue = tool;\n btn.innerHTML = createIcon(toolIcon(tool), 14);\n btn.addEventListener('click', () => this.callbacks.onDrawingTool(tool as never));\n btn.addEventListener('contextmenu', (e) => {\n e.preventDefault();\n this.callbacks.onToggleFavorite?.(tool as never);\n });\n this.favoritesEl.appendChild(btn);\n }\n }\n\n private showFlyout(idx: number): void {\n const group = this.config.drawingToolGroups[idx];\n if (!group || group.tools.length <= 1) return;\n\n this.hideFlyout();\n\n const flyout = document.createElement('div');\n flyout.className = 'tcw-flyout';\n\n const header = document.createElement('div');\n header.className = 'tcw-flyout-header';\n header.textContent = group.label;\n flyout.appendChild(header);\n\n for (const tool of group.tools) {\n const item = document.createElement('button');\n item.className = 'tcw-flyout-item';\n item.textContent = tool.label;\n item.dataset.toolValue = tool.value;\n item.addEventListener('click', () => {\n this.callbacks.onDrawingTool(tool.value);\n this.hideFlyout();\n });\n if (this.callbacks.onToggleFavorite) {\n if (this.favorites.includes(tool.value)) item.classList.add('tcw-flyout-faved');\n item.title = 'Right-click to pin/unpin';\n item.addEventListener('contextmenu', (e) => {\n e.preventDefault();\n this.callbacks.onToggleFavorite?.(tool.value);\n });\n }\n flyout.appendChild(item);\n }\n\n this.flyoutEl = flyout;\n this.groupWraps[idx].appendChild(flyout);\n }\n\n private hideFlyout(): void {\n if (this.flyoutEl) {\n this.flyoutEl.remove();\n this.flyoutEl = null;\n }\n }\n\n update(state: WidgetState): void {\n // Cursor active\n if (this.cursorBtn) {\n this.cursorBtn.classList.toggle('tcw-active', state.activeTool === null);\n }\n\n // Group buttons\n const { drawingToolGroups } = this.config;\n for (let i = 0; i < drawingToolGroups.length; i++) {\n const isActive = drawingToolGroups[i].tools.some(t => t.value === state.activeTool);\n this.groupButtons[i].classList.toggle('tcw-active', isActive);\n }\n\n // Flyout items\n if (this.flyoutEl) {\n this.flyoutEl.querySelectorAll('.tcw-flyout-item').forEach((item) => {\n const el = item as HTMLElement;\n el.classList.toggle('tcw-active', el.dataset.toolValue === state.activeTool);\n });\n }\n\n // Magnet\n if (this.magnetBtn) {\n this.magnetBtn.classList.toggle('tcw-active', state.magnetEnabled);\n this.magnetBtn.title = state.magnetEnabled ? 'Magnet ON' : 'Magnet OFF';\n }\n }\n\n private divider(): HTMLDivElement {\n const d = document.createElement('div');\n d.className = 'tcw-sidebar-divider';\n return d;\n }\n\n destroy(): void {\n this.hideFlyout();\n this.el.remove();\n }\n}\n","import type { ChartSettingsState, SettingsCallbacks } from './types.js';\nimport { createIcon } from './icons.js';\n\ntype Tab = 'style' | 'display' | 'scale';\nconst TABS: Tab[] = ['style', 'display', 'scale'];\n\nexport class WidgetSettings {\n private callbacks: SettingsCallbacks;\n private backdrop: HTMLDivElement | null = null;\n private modal: HTMLDivElement | null = null;\n private currentTab: Tab = 'style';\n private currentSettings: ChartSettingsState | null = null;\n private bodyEl: HTMLDivElement | null = null;\n private tabButtons: HTMLButtonElement[] = [];\n\n constructor(callbacks: SettingsCallbacks) {\n this.callbacks = callbacks;\n }\n\n open(currentSettings: ChartSettingsState): void {\n this.currentSettings = { ...currentSettings };\n this.currentTab = 'style';\n this.buildModal();\n }\n\n close(): void {\n this.backdrop?.remove();\n this.modal?.remove();\n this.backdrop = null;\n this.modal = null;\n this.bodyEl = null;\n this.tabButtons = [];\n }\n\n private buildModal(): void {\n // Backdrop\n this.backdrop = document.createElement('div');\n this.backdrop.className = 'tcw-modal-backdrop';\n this.backdrop.addEventListener('click', () => {\n this.callbacks.onClose();\n this.close();\n });\n document.body.appendChild(this.backdrop);\n\n // Modal\n this.modal = document.createElement('div');\n this.modal.className = 'tcw-modal';\n\n // Header\n const header = document.createElement('div');\n header.className = 'tcw-modal-header';\n const h3 = document.createElement('h3');\n h3.textContent = 'Chart Settings';\n header.appendChild(h3);\n const closeBtn = document.createElement('button');\n closeBtn.className = 'tcw-modal-close';\n closeBtn.innerHTML = createIcon('x', 16);\n closeBtn.addEventListener('click', () => {\n this.callbacks.onClose();\n this.close();\n });\n header.appendChild(closeBtn);\n this.modal.appendChild(header);\n\n // Tabs\n const tabsEl = document.createElement('div');\n tabsEl.className = 'tcw-modal-tabs';\n this.tabButtons = [];\n for (const tab of TABS) {\n const btn = document.createElement('button');\n btn.className = 'tcw-modal-tab';\n btn.textContent = tab;\n btn.dataset.tab = tab;\n if (tab === this.currentTab) btn.classList.add('tcw-active');\n btn.addEventListener('click', () => {\n this.currentTab = tab;\n this.tabButtons.forEach(b => b.classList.toggle('tcw-active', b.dataset.tab === tab));\n this.renderTabContent();\n });\n tabsEl.appendChild(btn);\n this.tabButtons.push(btn);\n }\n this.modal.appendChild(tabsEl);\n\n // Body\n this.bodyEl = document.createElement('div');\n this.bodyEl.className = 'tcw-modal-body';\n this.modal.appendChild(this.bodyEl);\n this.renderTabContent();\n\n // Footer\n const footer = document.createElement('div');\n footer.className = 'tcw-modal-footer';\n const resetBtn = document.createElement('button');\n resetBtn.className = 'tcw-reset-link';\n resetBtn.textContent = 'Reset to defaults';\n resetBtn.addEventListener('click', () => this.callbacks.onReset());\n footer.appendChild(resetBtn);\n const doneBtn = document.createElement('button');\n doneBtn.className = 'tcw-done-btn';\n doneBtn.textContent = 'Done';\n doneBtn.addEventListener('click', () => {\n this.callbacks.onClose();\n this.close();\n });\n footer.appendChild(doneBtn);\n this.modal.appendChild(footer);\n\n document.body.appendChild(this.modal);\n\n // Escape key\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n document.removeEventListener('keydown', onKeyDown);\n this.callbacks.onClose();\n this.close();\n }\n };\n document.addEventListener('keydown', onKeyDown);\n }\n\n private renderTabContent(): void {\n if (!this.bodyEl || !this.currentSettings) return;\n this.bodyEl.innerHTML = '';\n\n switch (this.currentTab) {\n case 'style':\n this.renderStyleTab();\n break;\n case 'display':\n this.renderDisplayTab();\n break;\n case 'scale':\n this.renderScaleTab();\n break;\n }\n }\n\n private renderStyleTab(): void {\n if (!this.bodyEl || !this.currentSettings) return;\n const s = this.currentSettings;\n\n // Candle Colors\n const candleSection = this.section('Candle Colors');\n candleSection.appendChild(this.colorRow('Up Body', s.candleUpColor, (v) => this.patch({ candleUpColor: v })));\n candleSection.appendChild(this.colorRow('Down Body', s.candleDownColor, (v) => this.patch({ candleDownColor: v })));\n candleSection.appendChild(this.colorRow('Up Wick', s.candleUpWick, (v) => this.patch({ candleUpWick: v })));\n candleSection.appendChild(this.colorRow('Down Wick', s.candleDownWick, (v) => this.patch({ candleDownWick: v })));\n this.bodyEl.appendChild(candleSection);\n\n // Background\n const bgSection = this.section('Background');\n bgSection.appendChild(this.colorRow('Background', s.backgroundColor, (v) => this.patch({ backgroundColor: v })));\n bgSection.appendChild(this.colorRow('Grid', s.gridColor, (v) => this.patch({ gridColor: v })));\n this.bodyEl.appendChild(bgSection);\n }\n\n private renderDisplayTab(): void {\n if (!this.bodyEl || !this.currentSettings) return;\n const s = this.currentSettings;\n\n const section = this.section();\n section.appendChild(this.toggleRow('Grid Lines', s.gridVisible, (v) => this.patch({ gridVisible: v })));\n section.appendChild(this.toggleRow('Volume', s.volumeVisible, (v) => this.patch({ volumeVisible: v })));\n section.appendChild(this.toggleRow('Volume Profile', s.volumeProfileVisible, (v) => this.patch({ volumeProfileVisible: v })));\n section.appendChild(this.toggleRow('Market Profile (TPO)', s.marketProfileVisible, (v) => this.patch({ marketProfileVisible: v })));\n section.appendChild(this.toggleRow('MP split by session', s.marketProfileSplit, (v) => this.patch({ marketProfileSplit: v })));\n section.appendChild(this.toggleRow('MP letters (TPO)', s.marketProfileLetters, (v) => this.patch({ marketProfileLetters: v })));\n section.appendChild(this.rangeRow('MP buckets', s.marketProfileBuckets, 8, 200, 1, (v) => this.patch({ marketProfileBuckets: v })));\n section.appendChild(this.rangeRow('MP opacity', s.marketProfileOpacity, 0.05, 1, 0.05, (v) => this.patch({ marketProfileOpacity: v }), (v) => `${Math.round(v * 100)}%`));\n section.appendChild(this.toggleRow('Liquidity heatmap', s.depthHeatmapVisible, (v) => this.patch({ depthHeatmapVisible: v })));\n section.appendChild(this.rangeRow('Heatmap opacity', s.depthHeatmapOpacity, 0.1, 1, 0.05, (v) => this.patch({ depthHeatmapOpacity: v }), (v) => `${Math.round(v * 100)}%`));\n section.appendChild(this.toggleRow('Swing markers', s.pivotMarkersVisible, (v) => this.patch({ pivotMarkersVisible: v })));\n section.appendChild(this.rangeRow('Swing strength', s.pivotStrength, 2, 20, 1, (v) => this.patch({ pivotStrength: v })));\n section.appendChild(this.toggleRow('Swing structure (HH/HL)', s.pivotStructureLabels, (v) => this.patch({ pivotStructureLabels: v })));\n section.appendChild(this.toggleRow('Session shading (RTH)', s.sessionShadingVisible, (v) => this.patch({ sessionShadingVisible: v })));\n section.appendChild(this.toggleRow('Prior-period levels', s.periodLevelsVisible, (v) => this.patch({ periodLevelsVisible: v })));\n section.appendChild(this.selectRow('Period levels basis', s.periodLevelsPeriod, [\n { value: 'day', label: 'Prior Day (PDH/PDL)' },\n { value: 'week', label: 'Prior Week (PWH/PWL)' },\n ], (v) => this.patch({ periodLevelsPeriod: v as ChartSettingsState['periodLevelsPeriod'] })));\n section.appendChild(this.toggleRow('OHLC Legend', s.legendVisible, (v) => this.patch({ legendVisible: v })));\n section.appendChild(this.toggleRow('Bar Countdown', s.barCountdown, (v) => this.patch({ barCountdown: v })));\n\n // Crosshair mode\n section.appendChild(this.selectRow('Crosshair Mode', s.crosshairMode, [\n { label: 'Magnet', value: 'magnet' },\n { label: 'Normal', value: 'normal' },\n { label: 'Hidden', value: 'hidden' },\n ], (v) => this.patch({ crosshairMode: v as ChartSettingsState['crosshairMode'] })));\n\n // Number locale\n section.appendChild(this.selectRow('Timezone', s.timezone, [\n { value: 'local', label: 'Local' },\n { value: '0', label: 'UTC / London' },\n { value: '-300', label: 'New York (UTC-5)' },\n { value: '-360', label: 'Chicago (UTC-6)' },\n { value: '60', label: 'Frankfurt (UTC+1)' },\n { value: '480', label: 'Singapore/HK (UTC+8)' },\n { value: '540', label: 'Tokyo (UTC+9)' },\n { value: '330', label: 'Mumbai (UTC+5:30)' },\n ], (v) => this.patch({ timezone: v })));\n section.appendChild(this.selectRow('Number Locale', s.numberLocale, [\n { label: 'en-US (65,234.00)', value: 'en-US' },\n { label: 'de-DE (65.234,00)', value: 'de-DE' },\n { label: 'fr-FR (65 234,00)', value: 'fr-FR' },\n { label: 'vi-VN (65.234,00)', value: 'vi-VN' },\n { label: 'en-IN (65,234.00)', value: 'en-IN' },\n { label: 'ja-JP (65,234.00)', value: 'ja-JP' },\n ], (v) => this.patch({ numberLocale: v })));\n\n this.bodyEl.appendChild(section);\n }\n\n private renderScaleTab(): void {\n if (!this.bodyEl || !this.currentSettings) return;\n const s = this.currentSettings;\n\n const section = this.section();\n section.appendChild(this.toggleRow('Auto Scale', s.autoScale, (v) => this.patch({ autoScale: v })));\n section.appendChild(this.selectRow('Price Scale', s.scaleMode, [\n { value: 'regular', label: 'Regular' },\n { value: 'logarithmic', label: 'Logarithmic' },\n { value: 'percentage', label: 'Percentage' },\n { value: 'indexedTo100', label: 'Indexed to 100' },\n ], (v) => this.patch({ scaleMode: v as ChartSettingsState['scaleMode'] })));\n this.bodyEl.appendChild(section);\n }\n\n private patch(partial: Partial<ChartSettingsState>): void {\n if (this.currentSettings) {\n Object.assign(this.currentSettings, partial);\n }\n this.callbacks.onChange(partial);\n }\n\n private section(title?: string): HTMLDivElement {\n const div = document.createElement('div');\n div.className = 'tcw-settings-section';\n if (title) {\n const t = document.createElement('div');\n t.className = 'tcw-settings-section-title';\n t.textContent = title;\n div.appendChild(t);\n }\n return div;\n }\n\n private colorRow(label: string, value: string, onChange: (v: string) => void): HTMLDivElement {\n const row = document.createElement('div');\n row.className = 'tcw-settings-row';\n\n const lbl = document.createElement('span');\n lbl.className = 'tcw-settings-label';\n lbl.textContent = label;\n row.appendChild(lbl);\n\n const wrap = document.createElement('div');\n wrap.className = 'tcw-color-picker-wrap';\n\n const input = document.createElement('input');\n input.type = 'color';\n input.value = value;\n\n const hex = document.createElement('span');\n hex.className = 'tcw-color-hex';\n hex.textContent = value;\n\n input.addEventListener('input', () => {\n hex.textContent = input.value;\n onChange(input.value);\n });\n\n wrap.appendChild(input);\n wrap.appendChild(hex);\n row.appendChild(wrap);\n return row;\n }\n\n private toggleRow(label: string, value: boolean, onChange: (v: boolean) => void): HTMLDivElement {\n const row = document.createElement('div');\n row.className = 'tcw-settings-row';\n\n const lbl = document.createElement('span');\n lbl.className = 'tcw-settings-label';\n lbl.textContent = label;\n row.appendChild(lbl);\n\n const toggle = document.createElement('button');\n toggle.className = `tcw-toggle${value ? ' tcw-on' : ''}`;\n toggle.addEventListener('click', () => {\n const newVal = !toggle.classList.contains('tcw-on');\n toggle.classList.toggle('tcw-on', newVal);\n onChange(newVal);\n });\n row.appendChild(toggle);\n return row;\n }\n\n private selectRow(\n label: string,\n value: string,\n options: { label: string; value: string }[],\n onChange: (v: string) => void,\n ): HTMLDivElement {\n const row = document.createElement('div');\n row.className = 'tcw-settings-row';\n\n const lbl = document.createElement('span');\n lbl.className = 'tcw-settings-label';\n lbl.textContent = label;\n row.appendChild(lbl);\n\n const select = document.createElement('select');\n select.className = 'tcw-settings-select';\n for (const opt of options) {\n const o = document.createElement('option');\n o.value = opt.value;\n o.textContent = opt.label;\n if (opt.value === value) o.selected = true;\n select.appendChild(o);\n }\n select.addEventListener('change', () => onChange(select.value));\n row.appendChild(select);\n return row;\n }\n\n private rangeRow(\n label: string,\n value: number,\n min: number,\n max: number,\n step: number,\n onChange: (v: number) => void,\n format: (v: number) => string = (v) => String(v),\n ): HTMLDivElement {\n const row = document.createElement('div');\n row.className = 'tcw-settings-row';\n\n const lbl = document.createElement('span');\n lbl.className = 'tcw-settings-label';\n lbl.textContent = label;\n row.appendChild(lbl);\n\n const wrap = document.createElement('div');\n wrap.className = 'tcw-settings-range';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = String(min);\n input.max = String(max);\n input.step = String(step);\n input.value = String(value);\n\n const out = document.createElement('span');\n out.className = 'tcw-settings-range-val';\n out.textContent = format(value);\n\n input.addEventListener('input', () => {\n const v = Number(input.value);\n out.textContent = format(v);\n onChange(v);\n });\n\n wrap.appendChild(input);\n wrap.appendChild(out);\n row.appendChild(wrap);\n return row;\n }\n\n destroy(): void {\n this.close();\n }\n}\n","export class WidgetStatusBar {\n private el: HTMLDivElement;\n private dotEl: HTMLSpanElement;\n private messageEl: HTMLSpanElement;\n private infoEl: HTMLSpanElement;\n\n constructor(host: HTMLElement) {\n this.el = document.createElement('div');\n this.el.className = 'tcw-statusbar';\n\n const indicator = document.createElement('div');\n indicator.className = 'tcw-status-indicator';\n\n this.dotEl = document.createElement('span');\n this.dotEl.className = 'tcw-status-dot';\n indicator.appendChild(this.dotEl);\n\n this.messageEl = document.createElement('span');\n indicator.appendChild(this.messageEl);\n\n this.el.appendChild(indicator);\n\n this.infoEl = document.createElement('span');\n this.el.appendChild(this.infoEl);\n\n host.appendChild(this.el);\n }\n\n update(state: { connectionState: string; message: string; symbol: string; timeframe: string }): void {\n this.dotEl.className = 'tcw-status-dot';\n if (state.connectionState === 'connected') {\n this.dotEl.classList.add('tcw-connected');\n } else if (state.connectionState === 'error') {\n this.dotEl.classList.add('tcw-error');\n }\n\n this.messageEl.textContent = state.message;\n this.infoEl.textContent = `${state.symbol} ${state.timeframe}`;\n }\n\n destroy(): void {\n this.el.remove();\n }\n}\n","import type { ChartType, DrawingToolType, TimeFrame } from '@tradecanvas/commons';\n\nexport interface CommandItem {\n id: string;\n label: string;\n category: 'indicator' | 'chartType' | 'drawing' | 'timeframe' | 'action';\n shortcut?: string;\n active?: boolean;\n}\n\nexport interface CommandPaletteCallbacks {\n onIndicator: (id: string) => void;\n onChartType: (type: ChartType) => void;\n onDrawingTool: (tool: DrawingToolType) => void;\n onTimeframe: (tf: TimeFrame) => void;\n onAction: (id: string) => void;\n onClose: () => void;\n}\n\nexport class WidgetCommandPalette {\n private backdrop: HTMLDivElement | null = null;\n private modal: HTMLDivElement | null = null;\n private input: HTMLInputElement | null = null;\n private list: HTMLDivElement | null = null;\n private items: CommandItem[] = [];\n private filtered: CommandItem[] = [];\n private selectedIndex = 0;\n private callbacks: CommandPaletteCallbacks;\n private boundKeydown: (e: KeyboardEvent) => void;\n\n constructor(callbacks: CommandPaletteCallbacks) {\n this.callbacks = callbacks;\n this.boundKeydown = this.handleKeydown.bind(this);\n }\n\n open(items: CommandItem[]): void {\n if (this.backdrop) return;\n this.items = items;\n this.filtered = items;\n this.selectedIndex = 0;\n\n this.backdrop = document.createElement('div');\n this.backdrop.className = 'tcw-modal-backdrop';\n this.backdrop.addEventListener('click', () => this.close());\n\n this.modal = document.createElement('div');\n this.modal.className = 'tcw-cmd-palette';\n\n const header = document.createElement('div');\n header.className = 'tcw-cmd-header';\n\n const searchIcon = document.createElement('span');\n searchIcon.className = 'tcw-cmd-icon';\n searchIcon.textContent = '⌕';\n header.appendChild(searchIcon);\n\n this.input = document.createElement('input');\n this.input.className = 'tcw-cmd-input';\n this.input.type = 'text';\n this.input.placeholder = 'Search indicators, chart types, tools...';\n this.input.addEventListener('input', () => this.filter());\n header.appendChild(this.input);\n\n const hint = document.createElement('span');\n hint.className = 'tcw-cmd-hint';\n hint.textContent = 'ESC';\n header.appendChild(hint);\n\n this.modal.appendChild(header);\n\n this.list = document.createElement('div');\n this.list.className = 'tcw-cmd-list';\n this.modal.appendChild(this.list);\n\n const footer = document.createElement('div');\n footer.className = 'tcw-cmd-footer';\n footer.innerHTML = '<span>↑↓ Navigate</span><span>⏎ Select</span><span>Esc Close</span>';\n this.modal.appendChild(footer);\n\n document.body.appendChild(this.backdrop);\n document.body.appendChild(this.modal);\n\n this.renderList();\n this.input.focus();\n document.addEventListener('keydown', this.boundKeydown);\n }\n\n close(): void {\n document.removeEventListener('keydown', this.boundKeydown);\n this.backdrop?.remove();\n this.modal?.remove();\n this.backdrop = null;\n this.modal = null;\n this.input = null;\n this.list = null;\n this.callbacks.onClose();\n }\n\n isOpen(): boolean {\n return this.backdrop !== null;\n }\n\n private filter(): void {\n const query = this.input?.value.toLowerCase().trim() ?? '';\n if (!query) {\n this.filtered = this.items;\n } else {\n this.filtered = this.items.filter(item =>\n item.label.toLowerCase().includes(query) ||\n item.category.toLowerCase().includes(query) ||\n item.id.toLowerCase().includes(query),\n );\n }\n this.selectedIndex = 0;\n this.renderList();\n }\n\n private renderList(): void {\n if (!this.list) return;\n this.list.innerHTML = '';\n\n if (this.filtered.length === 0) {\n const empty = document.createElement('div');\n empty.className = 'tcw-cmd-empty';\n empty.textContent = 'No results found';\n this.list.appendChild(empty);\n return;\n }\n\n let currentCategory = '';\n for (let i = 0; i < this.filtered.length; i++) {\n const item = this.filtered[i];\n\n if (item.category !== currentCategory) {\n currentCategory = item.category;\n const label = document.createElement('div');\n label.className = 'tcw-cmd-category';\n label.textContent = this.categoryLabel(currentCategory);\n this.list.appendChild(label);\n }\n\n const row = document.createElement('button');\n row.className = 'tcw-cmd-item';\n if (i === this.selectedIndex) row.classList.add('tcw-selected');\n if (item.active) row.classList.add('tcw-active');\n row.dataset.index = String(i);\n\n const nameSpan = document.createElement('span');\n nameSpan.className = 'tcw-cmd-item-label';\n nameSpan.textContent = item.label;\n row.appendChild(nameSpan);\n\n if (item.active) {\n const check = document.createElement('span');\n check.className = 'tcw-cmd-check';\n check.textContent = '✓';\n row.appendChild(check);\n }\n\n if (item.shortcut) {\n const kbd = document.createElement('kbd');\n kbd.className = 'tcw-cmd-kbd';\n kbd.textContent = item.shortcut;\n row.appendChild(kbd);\n }\n\n row.addEventListener('click', () => this.select(i));\n row.addEventListener('mouseenter', () => {\n this.selectedIndex = i;\n this.updateSelection();\n });\n\n this.list.appendChild(row);\n }\n }\n\n private updateSelection(): void {\n if (!this.list) return;\n const items = this.list.querySelectorAll('.tcw-cmd-item');\n items.forEach((el, i) => {\n el.classList.toggle('tcw-selected', i === this.selectedIndex);\n });\n items[this.selectedIndex]?.scrollIntoView({ block: 'nearest' });\n }\n\n private select(index: number): void {\n const item = this.filtered[index];\n if (!item) return;\n\n switch (item.category) {\n case 'indicator':\n this.callbacks.onIndicator(item.id);\n break;\n case 'chartType':\n this.callbacks.onChartType(item.id as ChartType);\n break;\n case 'drawing':\n this.callbacks.onDrawingTool(item.id as DrawingToolType);\n break;\n case 'timeframe':\n this.callbacks.onTimeframe(item.id as TimeFrame);\n break;\n case 'action':\n this.callbacks.onAction(item.id);\n break;\n }\n this.close();\n }\n\n private handleKeydown(e: KeyboardEvent): void {\n switch (e.key) {\n case 'Escape':\n e.preventDefault();\n this.close();\n break;\n case 'ArrowDown':\n e.preventDefault();\n if (this.filtered.length > 0) {\n this.selectedIndex = (this.selectedIndex + 1) % this.filtered.length;\n this.updateSelection();\n }\n break;\n case 'ArrowUp':\n e.preventDefault();\n if (this.filtered.length > 0) {\n this.selectedIndex = (this.selectedIndex - 1 + this.filtered.length) % this.filtered.length;\n this.updateSelection();\n }\n break;\n case 'Enter':\n e.preventDefault();\n this.select(this.selectedIndex);\n break;\n }\n }\n\n private categoryLabel(cat: string): string {\n switch (cat) {\n case 'indicator': return 'Indicators';\n case 'chartType': return 'Chart Types';\n case 'drawing': return 'Drawing Tools';\n case 'timeframe': return 'Timeframes';\n case 'action': return 'Actions';\n default: return cat;\n }\n }\n\n destroy(): void {\n this.close();\n }\n}\n","/**\n * Lightweight fuzzy symbol picker. Reuses the command-palette CSS for visual\n * consistency. Scoring is a cheap subsequence match — good enough for symbol\n * lists in the low thousands without pulling in a fuzzy-search dependency.\n */\nexport interface SymbolSearchCallbacks {\n onPick: (symbol: string) => void;\n onClose: () => void;\n}\n\ninterface ScoredSymbol {\n symbol: string;\n score: number;\n}\n\nexport class WidgetSymbolSearch {\n private backdrop: HTMLDivElement | null = null;\n private modal: HTMLDivElement | null = null;\n private input: HTMLInputElement | null = null;\n private list: HTMLDivElement | null = null;\n private symbols: string[] = [];\n private current: string = '';\n private filtered: ScoredSymbol[] = [];\n private selectedIndex = 0;\n private callbacks: SymbolSearchCallbacks;\n private boundKeydown: (e: KeyboardEvent) => void;\n /** One-shot pick override — when set, this open() routes picks here instead. */\n private pickOverride: ((symbol: string) => void) | null = null;\n\n constructor(callbacks: SymbolSearchCallbacks) {\n this.callbacks = callbacks;\n this.boundKeydown = this.handleKeydown.bind(this);\n }\n\n open(symbols: string[], current: string, onPick?: (symbol: string) => void): void {\n if (this.backdrop) return;\n this.pickOverride = onPick ?? null;\n this.symbols = symbols;\n this.current = current;\n this.filtered = symbols.map(s => ({ symbol: s, score: 0 }));\n this.selectedIndex = Math.max(0, symbols.indexOf(current));\n\n this.backdrop = document.createElement('div');\n this.backdrop.className = 'tcw-modal-backdrop';\n this.backdrop.addEventListener('click', () => this.close());\n\n this.modal = document.createElement('div');\n this.modal.className = 'tcw-cmd-palette';\n\n const header = document.createElement('div');\n header.className = 'tcw-cmd-header';\n\n const icon = document.createElement('span');\n icon.className = 'tcw-cmd-icon';\n icon.innerHTML = svgSearch();\n header.appendChild(icon);\n\n this.input = document.createElement('input');\n this.input.className = 'tcw-cmd-input';\n this.input.type = 'text';\n this.input.placeholder = 'Search symbol… (e.g. BTC, ETH, AAPL)';\n this.input.autocomplete = 'off';\n this.input.spellcheck = false;\n this.input.addEventListener('input', () => this.filter());\n header.appendChild(this.input);\n\n const hint = document.createElement('span');\n hint.className = 'tcw-cmd-hint';\n hint.textContent = 'ESC';\n header.appendChild(hint);\n\n this.modal.appendChild(header);\n\n this.list = document.createElement('div');\n this.list.className = 'tcw-cmd-list';\n this.modal.appendChild(this.list);\n\n const footer = document.createElement('div');\n footer.className = 'tcw-cmd-footer';\n footer.innerHTML = '<span>↑↓ Navigate</span><span>⏎ Open</span><span>Esc Close</span>';\n this.modal.appendChild(footer);\n\n document.body.appendChild(this.backdrop);\n document.body.appendChild(this.modal);\n\n this.renderList();\n this.input.focus();\n document.addEventListener('keydown', this.boundKeydown);\n }\n\n close(): void {\n document.removeEventListener('keydown', this.boundKeydown);\n this.backdrop?.remove();\n this.modal?.remove();\n this.backdrop = null;\n this.modal = null;\n this.input = null;\n this.list = null;\n this.pickOverride = null;\n this.callbacks.onClose();\n }\n\n isOpen(): boolean {\n return this.backdrop !== null;\n }\n\n destroy(): void {\n this.close();\n }\n\n private filter(): void {\n const q = (this.input?.value ?? '').toUpperCase().trim();\n if (!q) {\n this.filtered = this.symbols.map(s => ({ symbol: s, score: 0 }));\n } else {\n this.filtered = this.symbols\n .map(s => ({ symbol: s, score: scoreMatch(s.toUpperCase(), q) }))\n .filter(r => r.score > 0)\n .sort((a, b) => b.score - a.score);\n }\n this.selectedIndex = 0;\n this.renderList();\n }\n\n private renderList(): void {\n if (!this.list) return;\n this.list.innerHTML = '';\n\n if (this.filtered.length === 0) {\n const empty = document.createElement('div');\n empty.className = 'tcw-cmd-empty';\n empty.textContent = 'No symbols match';\n this.list.appendChild(empty);\n return;\n }\n\n const query = (this.input?.value ?? '').toUpperCase().trim();\n for (let i = 0; i < this.filtered.length; i++) {\n const { symbol } = this.filtered[i];\n const row = document.createElement('button');\n row.className = 'tcw-cmd-item';\n if (i === this.selectedIndex) row.classList.add('tcw-selected');\n if (symbol === this.current) row.classList.add('tcw-active');\n\n const label = document.createElement('span');\n label.className = 'tcw-cmd-item-label';\n label.innerHTML = highlight(symbol, query);\n row.appendChild(label);\n\n if (symbol === this.current) {\n const check = document.createElement('span');\n check.className = 'tcw-cmd-check';\n check.textContent = '✓';\n row.appendChild(check);\n }\n\n row.addEventListener('click', () => this.pick(i));\n row.addEventListener('mouseenter', () => {\n this.selectedIndex = i;\n this.updateSelection();\n });\n\n this.list.appendChild(row);\n }\n }\n\n private updateSelection(): void {\n if (!this.list) return;\n const items = this.list.querySelectorAll('.tcw-cmd-item');\n items.forEach((el, i) => el.classList.toggle('tcw-selected', i === this.selectedIndex));\n items[this.selectedIndex]?.scrollIntoView({ block: 'nearest' });\n }\n\n private pick(index: number): void {\n const entry = this.filtered[index];\n if (!entry) return;\n const override = this.pickOverride;\n if (override) override(entry.symbol);\n else this.callbacks.onPick(entry.symbol);\n this.close();\n }\n\n private handleKeydown(e: KeyboardEvent): void {\n switch (e.key) {\n case 'Escape':\n e.preventDefault();\n this.close();\n break;\n case 'ArrowDown':\n e.preventDefault();\n if (this.filtered.length > 0) {\n this.selectedIndex = (this.selectedIndex + 1) % this.filtered.length;\n this.updateSelection();\n }\n break;\n case 'ArrowUp':\n e.preventDefault();\n if (this.filtered.length > 0) {\n this.selectedIndex = (this.selectedIndex - 1 + this.filtered.length) % this.filtered.length;\n this.updateSelection();\n }\n break;\n case 'Enter':\n e.preventDefault();\n this.pick(this.selectedIndex);\n break;\n }\n }\n}\n\n/**\n * Cheap fuzzy score:\n * exact match → 1000\n * starts-with → 500 + tighter-prefix bonus\n * subsequence match → 100 − gap penalty\n * no match → 0\n */\nfunction scoreMatch(symbol: string, query: string): number {\n if (symbol === query) return 1000;\n if (symbol.startsWith(query)) return 500 + (50 - Math.min(50, symbol.length - query.length));\n if (symbol.includes(query)) return 200 + (50 - Math.min(50, symbol.length - query.length));\n\n let qi = 0;\n let lastIdx = -1;\n let gapPenalty = 0;\n for (let i = 0; i < symbol.length && qi < query.length; i++) {\n if (symbol[i] === query[qi]) {\n if (lastIdx >= 0) gapPenalty += i - lastIdx - 1;\n lastIdx = i;\n qi++;\n }\n }\n if (qi < query.length) return 0;\n return 100 - Math.min(99, gapPenalty);\n}\n\nfunction highlight(symbol: string, query: string): string {\n if (!query) return escapeHtml(symbol);\n const upper = symbol.toUpperCase();\n let out = '';\n let qi = 0;\n for (let i = 0; i < symbol.length; i++) {\n if (qi < query.length && upper[i] === query[qi]) {\n out += `<mark style=\"background:transparent;color:var(--tcw-accent);font-weight:700\">${escapeHtml(symbol[i])}</mark>`;\n qi++;\n } else {\n out += escapeHtml(symbol[i]);\n }\n }\n return out;\n}\n\nfunction escapeHtml(s: string): string {\n return s.replace(/[&<>\"']/g, ch => ({\n '&': '&', '<': '<', '>': '>', '\"': '"', \"'\": ''',\n } as Record<string, string>)[ch]);\n}\n\nfunction svgSearch(): string {\n return '<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"11\" cy=\"11\" r=\"7\"/><path d=\"m21 21-4.3-4.3\"/></svg>';\n}\n","/**\n * Keyboard-shortcut reference sheet. Bound to `?` (and `Shift+/`). Surfaces\n * shortcuts so users discover the widget's hidden interaction model — a\n * premium-feel detail TradingView, Linear, Figma, etc. all ship.\n */\nexport interface HotkeySheetCallbacks {\n onClose: () => void;\n}\n\ninterface HotkeyEntry {\n keys: string[];\n label: string;\n}\n\ninterface HotkeyGroup {\n title: string;\n entries: HotkeyEntry[];\n}\n\nconst isMac =\n typeof navigator !== 'undefined' && /mac|iphone|ipad|ipod/i.test(navigator.platform || navigator.userAgent);\nconst mod = isMac ? '⌘' : 'Ctrl';\n\nconst GROUPS: HotkeyGroup[] = [\n {\n title: 'Search & navigation',\n entries: [\n { keys: [mod, 'K'], label: 'Command palette' },\n { keys: [mod, 'P'], label: 'Symbol search' },\n { keys: ['?'], label: 'Show this sheet' },\n ],\n },\n {\n title: 'Chart manipulation',\n entries: [\n { keys: ['Shift', 'Drag'], label: 'Measure tool (bars × price Δ)' },\n { keys: ['Drag', 'Price axis'], label: 'Compress / expand vertical scale' },\n { keys: ['Drag', 'Time axis'], label: 'Zoom time axis' },\n { keys: ['Double-click', 'Price axis'], label: 'Re-enable auto-scale' },\n { keys: ['Double-click', 'Time axis'], label: 'Fit content' },\n { keys: ['Scroll'], label: 'Zoom around cursor' },\n ],\n },\n {\n title: 'Touch (mobile / tablet)',\n entries: [\n { keys: ['1 finger', 'Drag'], label: 'Pan / move crosshair' },\n { keys: ['2 fingers', 'Pinch'], label: 'Zoom around midpoint' },\n { keys: ['Long-press'], label: 'Pin OHLC tooltip at bar' },\n { keys: ['Drag', 'Axis strip'], label: 'Scale price / time axis' },\n ],\n },\n {\n title: 'Keyboard',\n entries: [\n { keys: ['←', '→'], label: 'Pan one bar' },\n { keys: ['+', '−'], label: 'Zoom in / out' },\n { keys: ['Home'], label: 'Scroll to start' },\n { keys: ['End'], label: 'Scroll to end (live edge)' },\n { keys: ['F'], label: 'Fit content' },\n ],\n },\n {\n title: 'Drawing',\n entries: [\n { keys: [mod, 'Z'], label: 'Undo' },\n { keys: [mod, 'Shift', 'Z'], label: 'Redo' },\n { keys: ['Esc'], label: 'Cancel active drawing' },\n ],\n },\n];\n\nexport class WidgetHotkeySheet {\n private backdrop: HTMLDivElement | null = null;\n private modal: HTMLDivElement | null = null;\n private callbacks: HotkeySheetCallbacks;\n private boundKeydown: (e: KeyboardEvent) => void;\n\n constructor(callbacks: HotkeySheetCallbacks) {\n this.callbacks = callbacks;\n this.boundKeydown = (e) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n this.close();\n }\n };\n }\n\n open(): void {\n if (this.backdrop) return;\n\n this.backdrop = document.createElement('div');\n this.backdrop.className = 'tcw-modal-backdrop';\n this.backdrop.addEventListener('click', () => this.close());\n\n this.modal = document.createElement('div');\n this.modal.className = 'tcw-modal tcw-hotkey-sheet';\n this.modal.style.width = '640px';\n\n const header = document.createElement('div');\n header.className = 'tcw-modal-header';\n header.innerHTML = '<h3>Keyboard shortcuts</h3>';\n const closeBtn = document.createElement('button');\n closeBtn.className = 'tcw-modal-close';\n closeBtn.setAttribute('aria-label', 'Close');\n closeBtn.innerHTML = '×';\n closeBtn.addEventListener('click', () => this.close());\n header.appendChild(closeBtn);\n this.modal.appendChild(header);\n\n const body = document.createElement('div');\n body.className = 'tcw-modal-body';\n\n const grid = document.createElement('div');\n grid.className = 'tcw-hotkey-grid';\n\n for (const group of GROUPS) {\n const section = document.createElement('section');\n section.className = 'tcw-hotkey-section';\n const title = document.createElement('div');\n title.className = 'tcw-settings-section-title';\n title.textContent = group.title;\n section.appendChild(title);\n\n for (const entry of group.entries) {\n const row = document.createElement('div');\n row.className = 'tcw-hotkey-row';\n\n const keys = document.createElement('div');\n keys.className = 'tcw-hotkey-keys';\n for (let i = 0; i < entry.keys.length; i++) {\n if (i > 0) {\n const plus = document.createElement('span');\n plus.className = 'tcw-hotkey-sep';\n plus.textContent = '+';\n keys.appendChild(plus);\n }\n const kbd = document.createElement('kbd');\n kbd.className = 'tcw-cmd-kbd';\n kbd.textContent = entry.keys[i];\n keys.appendChild(kbd);\n }\n row.appendChild(keys);\n\n const label = document.createElement('span');\n label.className = 'tcw-hotkey-label';\n label.textContent = entry.label;\n row.appendChild(label);\n\n section.appendChild(row);\n }\n\n grid.appendChild(section);\n }\n\n body.appendChild(grid);\n this.modal.appendChild(body);\n\n const footer = document.createElement('div');\n footer.className = 'tcw-modal-footer';\n footer.innerHTML = '<span style=\"font-size:11px;color:var(--tcw-text-muted)\">Press ? anytime to show this sheet</span>';\n const ok = document.createElement('button');\n ok.className = 'tcw-done-btn';\n ok.textContent = 'Got it';\n ok.addEventListener('click', () => this.close());\n footer.appendChild(ok);\n this.modal.appendChild(footer);\n\n document.body.appendChild(this.backdrop);\n document.body.appendChild(this.modal);\n\n document.addEventListener('keydown', this.boundKeydown);\n }\n\n close(): void {\n document.removeEventListener('keydown', this.boundKeydown);\n this.backdrop?.remove();\n this.modal?.remove();\n this.backdrop = null;\n this.modal = null;\n this.callbacks.onClose();\n }\n\n isOpen(): boolean {\n return this.backdrop !== null;\n }\n\n destroy(): void {\n this.close();\n }\n}\n","/**\n * Replay scrubber bar — surfaces the chart's existing replay engine as a\n * visible bottom-of-chart control. Mounts under the chart container, owns\n * its own lifecycle, and reports user intent up via callbacks (no chart\n * coupling — the host calls chart.replayStart() / replayPause() / etc.).\n */\nexport interface ReplayBarCallbacks {\n onPlay: () => void;\n onPause: () => void;\n onStop: () => void;\n onStepBack: () => void;\n onStepForward: () => void;\n onSeek: (index: number) => void;\n onSpeedChange: (barsPerSecond: number) => void;\n onClose: () => void;\n}\n\nexport type ReplayBarState = 'playing' | 'paused' | 'stopped';\n\nconst SPEEDS = [0.5, 1, 2, 5, 10, 20, 50, 100];\n\nexport class WidgetReplayBar {\n private root: HTMLDivElement | null = null;\n private scrubber: HTMLInputElement | null = null;\n private progressLabel: HTMLSpanElement | null = null;\n private playBtn: HTMLButtonElement | null = null;\n private state: ReplayBarState = 'stopped';\n private total = 0;\n private speed = 5;\n private callbacks: ReplayBarCallbacks;\n\n constructor(callbacks: ReplayBarCallbacks) {\n this.callbacks = callbacks;\n }\n\n mount(host: HTMLElement, opts: { total: number; speed?: number }): void {\n if (this.root) return;\n this.total = Math.max(0, opts.total);\n this.speed = opts.speed ?? 5;\n this.state = 'paused';\n\n this.root = document.createElement('div');\n this.root.className = 'tcw-replay-bar';\n this.root.innerHTML = this.markup();\n\n host.appendChild(this.root);\n this.wireEvents();\n this.syncUi();\n }\n\n unmount(): void {\n this.root?.remove();\n this.root = null;\n this.scrubber = null;\n this.progressLabel = null;\n this.playBtn = null;\n this.state = 'stopped';\n }\n\n isMounted(): boolean {\n return this.root !== null;\n }\n\n setState(state: ReplayBarState): void {\n this.state = state;\n this.syncUi();\n }\n\n setProgress(current: number, total: number): void {\n this.total = total;\n if (this.scrubber) {\n this.scrubber.max = String(Math.max(0, total - 1));\n this.scrubber.value = String(current);\n }\n if (this.progressLabel) {\n this.progressLabel.textContent = `${current + 1} / ${total}`;\n }\n }\n\n destroy(): void {\n this.unmount();\n }\n\n private markup(): string {\n const speeds = SPEEDS.map(s => `<option value=\"${s}\"${s === this.speed ? ' selected' : ''}>${s}× bars/s</option>`).join('');\n return `\n <button class=\"tcw-replay-btn\" data-act=\"close\" title=\"Exit replay\" aria-label=\"Exit replay\">${svgX()}</button>\n <button class=\"tcw-replay-btn\" data-act=\"stepBack\" title=\"Step back\" aria-label=\"Step back\">${svgStepBack()}</button>\n <button class=\"tcw-replay-btn tcw-replay-play\" data-act=\"play\" title=\"Play / pause\" aria-label=\"Play / pause\">${svgPlay()}</button>\n <button class=\"tcw-replay-btn\" data-act=\"stepForward\" title=\"Step forward\" aria-label=\"Step forward\">${svgStepForward()}</button>\n <input type=\"range\" class=\"tcw-replay-scrubber\" data-act=\"seek\" min=\"0\" max=\"${Math.max(0, this.total - 1)}\" value=\"0\" step=\"1\" />\n <span class=\"tcw-replay-progress\" data-tcw=\"progress\">1 / ${this.total}</span>\n <select class=\"tcw-replay-speed\" data-act=\"speed\">${speeds}</select>\n `;\n }\n\n private wireEvents(): void {\n if (!this.root) return;\n this.scrubber = this.root.querySelector('input[data-act=\"seek\"]');\n this.progressLabel = this.root.querySelector('[data-tcw=\"progress\"]');\n this.playBtn = this.root.querySelector('button[data-act=\"play\"]');\n\n this.root.querySelector('[data-act=\"close\"]')?.addEventListener('click', () => this.callbacks.onClose());\n this.root.querySelector('[data-act=\"stepBack\"]')?.addEventListener('click', () => this.callbacks.onStepBack());\n this.root.querySelector('[data-act=\"stepForward\"]')?.addEventListener('click', () => this.callbacks.onStepForward());\n this.playBtn?.addEventListener('click', () => {\n if (this.state === 'playing') {\n this.callbacks.onPause();\n } else {\n this.callbacks.onPlay();\n }\n });\n this.scrubber?.addEventListener('input', () => {\n const idx = Number(this.scrubber!.value);\n this.callbacks.onSeek(idx);\n });\n (this.root.querySelector('[data-act=\"speed\"]') as HTMLSelectElement | null)?.addEventListener('change', (e) => {\n const v = Number((e.target as HTMLSelectElement).value);\n this.speed = v;\n this.callbacks.onSpeedChange(v);\n });\n }\n\n private syncUi(): void {\n if (!this.playBtn) return;\n this.playBtn.innerHTML = this.state === 'playing' ? svgPause() : svgPlay();\n this.playBtn.title = this.state === 'playing' ? 'Pause' : 'Play';\n }\n}\n\nfunction svgPlay(): string {\n return '<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M8 5v14l11-7L8 5z\"/></svg>';\n}\nfunction svgPause(): string {\n return '<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/></svg>';\n}\nfunction svgStepBack(): string {\n return '<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M6 6h2v12H6zM20 6L9 12l11 6V6z\"/></svg>';\n}\nfunction svgStepForward(): string {\n return '<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M4 6l11 6L4 18V6zM16 6h2v12h-2z\"/></svg>';\n}\nfunction svgX(): string {\n return '<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M18 6L6 18M6 6l12 12\"/></svg>';\n}\n","/**\n * Watchlist sidebar — vertical list of symbols, each with last price, %\n * change, and a mini sparkline. Clicking switches the chart's symbol.\n *\n * The widget tracks the *active* symbol's price/spark automatically from the\n * live stream. For non-active symbols, the host can push data via\n * `setEntry(symbol, …)` so the row reflects whatever the app already has.\n */\nexport interface WatchlistEntry {\n symbol: string;\n lastPrice?: number;\n /** Reference price for % calc (usually session open or 24h-ago close). */\n refPrice?: number;\n /** Recent close samples for the sparkline — last point is the live price. */\n sparkline?: number[];\n}\n\nexport interface WatchlistCallbacks {\n onSelect: (symbol: string) => void;\n}\n\nexport class WidgetWatchlist {\n private el: HTMLDivElement;\n private listEl: HTMLDivElement;\n private rowMap = new Map<string, {\n row: HTMLDivElement;\n priceEl: HTMLSpanElement;\n changeEl: HTMLSpanElement;\n sparkCanvas: HTMLCanvasElement;\n }>();\n private entries = new Map<string, WatchlistEntry>();\n private active: string | null = null;\n private callbacks: WatchlistCallbacks;\n\n constructor(host: HTMLElement, symbols: string[], callbacks: WatchlistCallbacks) {\n this.callbacks = callbacks;\n\n this.el = document.createElement('div');\n this.el.className = 'tcw-watchlist';\n\n const header = document.createElement('div');\n header.className = 'tcw-watchlist-header';\n header.textContent = 'Watchlist';\n this.el.appendChild(header);\n\n this.listEl = document.createElement('div');\n this.listEl.className = 'tcw-watchlist-list';\n this.el.appendChild(this.listEl);\n\n for (const symbol of symbols) {\n this.entries.set(symbol, { symbol });\n this.appendRow(symbol);\n }\n\n host.appendChild(this.el);\n }\n\n /** Replace the symbol set. Rows are diff'd so DOM churn is minimal. */\n setSymbols(symbols: string[]): void {\n const next = new Set(symbols);\n for (const sym of this.rowMap.keys()) {\n if (!next.has(sym)) this.removeRow(sym);\n }\n for (const sym of symbols) {\n if (!this.rowMap.has(sym)) {\n this.entries.set(sym, this.entries.get(sym) ?? { symbol: sym });\n this.appendRow(sym);\n }\n }\n }\n\n setActive(symbol: string): void {\n if (this.active === symbol) return;\n if (this.active && this.rowMap.has(this.active)) {\n this.rowMap.get(this.active)!.row.classList.remove('tcw-watchlist-active');\n }\n this.active = symbol;\n const cur = this.rowMap.get(symbol);\n if (cur) cur.row.classList.add('tcw-watchlist-active');\n }\n\n /** Push a price tick into a row. The widget calls this automatically for\n * the active symbol. Apps can call it for the rest. */\n setEntry(symbol: string, patch: Partial<WatchlistEntry>): void {\n const prev = this.entries.get(symbol) ?? { symbol };\n const next = { ...prev, ...patch };\n this.entries.set(symbol, next);\n this.renderRow(symbol);\n }\n\n destroy(): void {\n this.el.remove();\n this.rowMap.clear();\n this.entries.clear();\n }\n\n private appendRow(symbol: string): void {\n const row = document.createElement('div');\n row.className = 'tcw-watchlist-row';\n row.tabIndex = 0;\n\n const label = document.createElement('div');\n label.className = 'tcw-watchlist-symbol';\n label.textContent = formatSymbol(symbol);\n\n const spark = document.createElement('canvas');\n spark.className = 'tcw-watchlist-spark';\n spark.width = 64;\n spark.height = 22;\n\n const right = document.createElement('div');\n right.className = 'tcw-watchlist-stats';\n const priceEl = document.createElement('span');\n priceEl.className = 'tcw-watchlist-price';\n priceEl.textContent = '—';\n const changeEl = document.createElement('span');\n changeEl.className = 'tcw-watchlist-change';\n changeEl.textContent = '';\n right.appendChild(priceEl);\n right.appendChild(changeEl);\n\n row.appendChild(label);\n row.appendChild(spark);\n row.appendChild(right);\n\n row.addEventListener('click', () => this.callbacks.onSelect(symbol));\n row.addEventListener('keydown', (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n this.callbacks.onSelect(symbol);\n }\n });\n\n this.listEl.appendChild(row);\n this.rowMap.set(symbol, { row, priceEl, changeEl, sparkCanvas: spark });\n if (symbol === this.active) row.classList.add('tcw-watchlist-active');\n }\n\n private removeRow(symbol: string): void {\n const ref = this.rowMap.get(symbol);\n if (!ref) return;\n ref.row.remove();\n this.rowMap.delete(symbol);\n }\n\n private renderRow(symbol: string): void {\n const ref = this.rowMap.get(symbol);\n const entry = this.entries.get(symbol);\n if (!ref || !entry) return;\n\n if (entry.lastPrice !== undefined) {\n ref.priceEl.textContent = formatPrice(entry.lastPrice);\n }\n\n if (entry.lastPrice !== undefined && entry.refPrice !== undefined && entry.refPrice !== 0) {\n const diff = entry.lastPrice - entry.refPrice;\n const pct = (diff / entry.refPrice) * 100;\n const sign = diff >= 0 ? '+' : '';\n ref.changeEl.textContent = `${sign}${pct.toFixed(2)}%`;\n ref.changeEl.className = `tcw-watchlist-change ${diff >= 0 ? 'tcw-up' : 'tcw-down'}`;\n } else {\n ref.changeEl.textContent = '';\n }\n\n if (entry.sparkline && entry.sparkline.length >= 2) {\n drawSparkline(ref.sparkCanvas, entry.sparkline, entry.refPrice ?? entry.sparkline[0]);\n }\n }\n}\n\nfunction formatSymbol(symbol: string): string {\n // Add a / separator for typical crypto pair suffixes; leaves stock tickers\n // (AAPL, NVDA) alone.\n for (const quote of ['USDT', 'USD', 'BTC', 'ETH', 'EUR']) {\n if (symbol.length > quote.length && symbol.endsWith(quote)) {\n return symbol.slice(0, -quote.length) + '/' + quote;\n }\n }\n return symbol;\n}\n\nfunction formatPrice(v: number): string {\n if (v === 0) return '0';\n const abs = Math.abs(v);\n if (abs >= 1000) return v.toFixed(2);\n if (abs >= 1) return v.toFixed(4);\n return v.toPrecision(4);\n}\n\nfunction drawSparkline(canvas: HTMLCanvasElement, samples: number[], ref: number): void {\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n const dpr = window.devicePixelRatio || 1;\n if (canvas.width !== canvas.clientWidth * dpr) {\n canvas.width = (canvas.clientWidth || 64) * dpr;\n canvas.height = (canvas.clientHeight || 22) * dpr;\n }\n const w = canvas.width;\n const h = canvas.height;\n\n let lo = Infinity, hi = -Infinity;\n for (const v of samples) {\n if (v < lo) lo = v;\n if (v > hi) hi = v;\n }\n const span = Math.max(hi - lo, 1e-9);\n const last = samples[samples.length - 1];\n const up = last >= ref;\n const color = up ? '#26a17b' : '#f23645';\n\n ctx.clearRect(0, 0, w, h);\n ctx.lineWidth = 1.4 * dpr;\n ctx.strokeStyle = color;\n ctx.beginPath();\n const step = w / (samples.length - 1);\n for (let i = 0; i < samples.length; i++) {\n const x = i * step;\n const y = h - ((samples[i] - lo) / span) * (h - 4) - 2;\n if (i === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y);\n }\n ctx.stroke();\n}\n","import type { AlertCondition } from '@tradecanvas/core';\nimport { createIcon } from './icons.js';\n\nexport interface AlertListItem {\n id: string;\n price: number;\n condition: string;\n message?: string;\n triggered: boolean;\n channel?: string;\n label?: string;\n}\n\nexport interface AlertSource {\n /** `'price'` or `<instanceId>:<key>`. */\n channel: string;\n label: string;\n}\n\nexport interface AlertsPanelCallbacks {\n onAdd: (price: number, condition: AlertCondition, message: string | undefined, channel: string, label: string) => void;\n onRemove: (id: string) => void;\n onClear: () => void;\n /** Latest value for a source channel, used to prefill the add form. */\n getChannelValue: (channel: string) => number | null;\n formatPrice: (price: number) => string;\n}\n\nconst CONDITION_OPTIONS: { value: AlertCondition; label: string }[] = [\n { value: 'crossing', label: 'Crossing' },\n { value: 'crossingUp', label: 'Crossing up' },\n { value: 'crossingDown', label: 'Crossing down' },\n { value: 'greaterThan', label: 'Greater than' },\n { value: 'lessThan', label: 'Less than' },\n];\n\nconst CONDITION_LABEL = new Map(CONDITION_OPTIONS.map((o) => [o.value, o.label]));\n\nfunction roundForInput(v: number): number {\n return Math.round(v * 1e6) / 1e6;\n}\n\nfunction formatPlain(v: number): string {\n const abs = Math.abs(v);\n return abs >= 1000 ? v.toFixed(2) : abs >= 1 ? v.toFixed(2) : v.toPrecision(4);\n}\n\n/**\n * Floating price-alerts panel. Lists current alerts (with condition, price,\n * message, and a delete control) and an inline form to add a new one prefilled\n * with the current price. Toggled from the toolbar bell button; the host wires\n * add/remove back to the chart's `AlertManager`.\n */\nexport class WidgetAlertsPanel {\n private el: HTMLDivElement;\n private listEl: HTMLDivElement;\n private priceInput: HTMLInputElement;\n private conditionSelect: HTMLSelectElement;\n private sourceSelect: HTMLSelectElement;\n private messageInput: HTMLInputElement;\n private emptyEl: HTMLDivElement;\n private callbacks: AlertsPanelCallbacks;\n private open = false;\n private alerts: AlertListItem[] = [];\n private sources: AlertSource[] = [{ channel: 'price', label: 'Price' }];\n\n constructor(host: HTMLElement, callbacks: AlertsPanelCallbacks) {\n this.callbacks = callbacks;\n\n this.el = document.createElement('div');\n this.el.className = 'tcw-alerts-panel';\n this.el.hidden = true;\n\n // Header\n const header = document.createElement('div');\n header.className = 'tcw-alerts-header';\n const title = document.createElement('span');\n title.textContent = 'Price Alerts';\n const closeBtn = document.createElement('button');\n closeBtn.className = 'tcw-alerts-close';\n closeBtn.type = 'button';\n closeBtn.setAttribute('aria-label', 'Close alerts');\n closeBtn.innerHTML = createIcon('x', 14);\n closeBtn.addEventListener('click', () => this.close());\n header.appendChild(title);\n header.appendChild(closeBtn);\n this.el.appendChild(header);\n\n // Add form\n const form = document.createElement('form');\n form.className = 'tcw-alerts-form';\n\n this.sourceSelect = document.createElement('select');\n this.sourceSelect.className = 'tcw-alerts-source';\n this.sourceSelect.addEventListener('change', () => this.prefillPrice());\n\n this.priceInput = document.createElement('input');\n this.priceInput.type = 'number';\n this.priceInput.step = 'any';\n this.priceInput.placeholder = 'Value';\n this.priceInput.className = 'tcw-alerts-price';\n this.priceInput.required = true;\n\n this.conditionSelect = document.createElement('select');\n this.conditionSelect.className = 'tcw-alerts-condition';\n for (const opt of CONDITION_OPTIONS) {\n const o = document.createElement('option');\n o.value = opt.value;\n o.textContent = opt.label;\n this.conditionSelect.appendChild(o);\n }\n\n this.messageInput = document.createElement('input');\n this.messageInput.type = 'text';\n this.messageInput.placeholder = 'Note (optional)';\n this.messageInput.className = 'tcw-alerts-message';\n\n const addBtn = document.createElement('button');\n addBtn.type = 'submit';\n addBtn.className = 'tcw-alerts-add';\n addBtn.innerHTML = `${createIcon('plus', 14)}<span>Add alert</span>`;\n\n form.appendChild(this.sourceSelect);\n form.appendChild(this.priceInput);\n form.appendChild(this.conditionSelect);\n form.appendChild(this.messageInput);\n form.appendChild(addBtn);\n form.addEventListener('submit', (e) => {\n e.preventDefault();\n this.submitForm();\n });\n this.el.appendChild(form);\n\n // List\n this.listEl = document.createElement('div');\n this.listEl.className = 'tcw-alerts-list';\n this.el.appendChild(this.listEl);\n\n this.emptyEl = document.createElement('div');\n this.emptyEl.className = 'tcw-alerts-empty';\n this.emptyEl.textContent = 'No alerts yet. Add one above, or right-click the chart.';\n this.listEl.appendChild(this.emptyEl);\n\n this.renderSources();\n host.appendChild(this.el);\n }\n\n /** Replace the alert-source options (price + indicator lines). */\n setSources(sources: AlertSource[]): void {\n this.sources = sources.length > 0 ? sources : [{ channel: 'price', label: 'Price' }];\n this.renderSources();\n }\n\n private renderSources(): void {\n const current = this.sourceSelect.value || 'price';\n this.sourceSelect.replaceChildren();\n for (const src of this.sources) {\n const o = document.createElement('option');\n o.value = src.channel;\n o.textContent = src.label;\n this.sourceSelect.appendChild(o);\n }\n // Keep the prior selection if it still exists, else default to price.\n this.sourceSelect.value = this.sources.some((s) => s.channel === current) ? current : 'price';\n }\n\n isOpen(): boolean {\n return this.open;\n }\n\n toggle(): void {\n this.open ? this.close() : this.openPanel();\n }\n\n openPanel(): void {\n this.open = true;\n this.el.hidden = false;\n if (this.priceInput.value === '') this.prefillPrice();\n }\n\n /** Fill the value input with the selected source's current value. */\n private prefillPrice(): void {\n const v = this.callbacks.getChannelValue(this.sourceSelect.value || 'price');\n this.priceInput.value = v !== null ? String(roundForInput(v)) : '';\n }\n\n close(): void {\n this.open = false;\n this.el.hidden = true;\n }\n\n /** Replace the displayed alert list. */\n setAlerts(alerts: AlertListItem[]): void {\n this.alerts = alerts;\n this.renderList();\n }\n\n destroy(): void {\n this.el.remove();\n }\n\n private submitForm(): void {\n const price = Number(this.priceInput.value);\n if (!Number.isFinite(price)) return;\n const condition = this.conditionSelect.value as AlertCondition;\n const message = this.messageInput.value.trim() || undefined;\n const channel = this.sourceSelect.value || 'price';\n const label = this.sources.find((s) => s.channel === channel)?.label ?? 'Price';\n this.callbacks.onAdd(price, condition, message, channel, label);\n this.messageInput.value = '';\n this.prefillPrice();\n }\n\n private renderList(): void {\n // Clear rows but keep the empty placeholder reference.\n this.listEl.replaceChildren();\n\n if (this.alerts.length === 0) {\n this.listEl.appendChild(this.emptyEl);\n return;\n }\n\n // Show most recent first.\n for (const alert of [...this.alerts].reverse()) {\n const row = document.createElement('div');\n row.className = 'tcw-alerts-row' + (alert.triggered ? ' tcw-alerts-triggered' : '');\n\n const info = document.createElement('div');\n info.className = 'tcw-alerts-info';\n const main = document.createElement('div');\n main.className = 'tcw-alerts-row-main';\n const label = CONDITION_LABEL.get(alert.condition as AlertCondition) ?? alert.condition;\n const isIndicator = alert.channel && alert.channel !== 'price';\n const valueStr = isIndicator ? formatPlain(alert.price) : this.callbacks.formatPrice(alert.price);\n const prefix = isIndicator && alert.label ? `${alert.label} ` : '';\n main.textContent = `${prefix}${label} ${valueStr}`;\n info.appendChild(main);\n if (alert.message) {\n const note = document.createElement('div');\n note.className = 'tcw-alerts-row-note';\n note.textContent = alert.message;\n info.appendChild(note);\n }\n if (alert.triggered) {\n const badge = document.createElement('span');\n badge.className = 'tcw-alerts-badge';\n badge.textContent = 'triggered';\n main.appendChild(badge);\n }\n\n const del = document.createElement('button');\n del.type = 'button';\n del.className = 'tcw-alerts-del';\n del.setAttribute('aria-label', 'Delete alert');\n del.innerHTML = createIcon('trash', 14);\n del.addEventListener('click', () => this.callbacks.onRemove(alert.id));\n\n row.appendChild(info);\n row.appendChild(del);\n this.listEl.appendChild(row);\n }\n }\n}\n","import { createIcon } from './icons.js';\n\nexport interface ObjectTreeIndicator {\n instanceId: string;\n name: string;\n visible: boolean;\n}\n\nexport interface ObjectTreeDrawing {\n id: string;\n label: string;\n visible: boolean;\n locked: boolean;\n}\n\nexport interface ObjectTreeCompare {\n id: string;\n label: string;\n color: string;\n}\n\nexport interface ObjectTreeCallbacks {\n onRemoveIndicator: (instanceId: string) => void;\n onConfigureIndicator?: (instanceId: string) => void;\n onToggleIndicatorVisible?: (instanceId: string, visible: boolean) => void;\n onRemoveDrawing: (id: string) => void;\n onToggleDrawingVisible: (id: string, visible: boolean) => void;\n onToggleDrawingLocked: (id: string, locked: boolean) => void;\n /** When provided, a Compare section with an \"add\" button is shown. */\n onAddCompare?: () => void;\n onRemoveCompare?: (id: string) => void;\n}\n\n/**\n * Object-tree panel — TradingView's layers manager. Lists every active\n * indicator and drawing on the chart with per-item controls: indicators can be\n * removed; drawings can be shown/hidden, locked/unlocked, and removed. Toggled\n * from the toolbar layers button; the host wires actions back to the chart.\n */\nexport class WidgetObjectTree {\n private el: HTMLDivElement;\n private indicatorsEl: HTMLDivElement;\n private drawingsEl: HTMLDivElement;\n private compareEl: HTMLDivElement | null = null;\n private callbacks: ObjectTreeCallbacks;\n private open = false;\n\n constructor(host: HTMLElement, callbacks: ObjectTreeCallbacks) {\n this.callbacks = callbacks;\n\n this.el = document.createElement('div');\n this.el.className = 'tcw-tree-panel';\n this.el.hidden = true;\n\n const header = document.createElement('div');\n header.className = 'tcw-tree-header';\n const title = document.createElement('span');\n title.textContent = 'Objects';\n const closeBtn = document.createElement('button');\n closeBtn.type = 'button';\n closeBtn.className = 'tcw-tree-close';\n closeBtn.setAttribute('aria-label', 'Close objects');\n closeBtn.innerHTML = createIcon('x', 14);\n closeBtn.addEventListener('click', () => this.close());\n header.appendChild(title);\n header.appendChild(closeBtn);\n this.el.appendChild(header);\n\n this.indicatorsEl = this.makeSection('Indicators');\n this.drawingsEl = this.makeSection('Drawings');\n if (this.callbacks.onAddCompare) {\n this.compareEl = this.makeSection('Compare', () => this.callbacks.onAddCompare?.());\n }\n\n host.appendChild(this.el);\n }\n\n isOpen(): boolean {\n return this.open;\n }\n\n toggle(): void {\n this.open ? this.close() : this.openPanel();\n }\n\n openPanel(): void {\n this.open = true;\n this.el.hidden = false;\n }\n\n close(): void {\n this.open = false;\n this.el.hidden = true;\n }\n\n destroy(): void {\n this.el.remove();\n }\n\n /** Replace all lists. Cheap full re-render — counts are small. */\n setObjects(\n indicators: ObjectTreeIndicator[],\n drawings: ObjectTreeDrawing[],\n compares: ObjectTreeCompare[] = [],\n ): void {\n this.renderIndicators(indicators);\n this.renderDrawings(drawings);\n this.renderCompares(compares);\n }\n\n private makeSection(title: string, onAdd?: () => void): HTMLDivElement {\n const wrap = document.createElement('div');\n wrap.className = 'tcw-tree-section';\n const head = document.createElement('div');\n head.className = 'tcw-tree-section-head';\n const label = document.createElement('span');\n label.textContent = title;\n head.appendChild(label);\n if (onAdd) {\n const addBtn = document.createElement('button');\n addBtn.type = 'button';\n addBtn.className = 'tcw-tree-add';\n addBtn.setAttribute('aria-label', `Add ${title.toLowerCase()}`);\n addBtn.title = `Add ${title.toLowerCase()}`;\n addBtn.innerHTML = createIcon('plus', 13);\n addBtn.addEventListener('click', onAdd);\n head.appendChild(addBtn);\n }\n const list = document.createElement('div');\n list.className = 'tcw-tree-list';\n wrap.appendChild(head);\n wrap.appendChild(list);\n this.el.appendChild(wrap);\n return list;\n }\n\n private renderIndicators(indicators: ObjectTreeIndicator[]): void {\n this.indicatorsEl.replaceChildren();\n if (indicators.length === 0) {\n this.indicatorsEl.appendChild(this.emptyRow('No indicators'));\n return;\n }\n for (const ind of indicators) {\n const row = this.row(ind.name);\n if (!ind.visible) row.classList.add('tcw-tree-hidden');\n const actions = document.createElement('div');\n actions.className = 'tcw-tree-actions';\n if (this.callbacks.onToggleIndicatorVisible) {\n actions.appendChild(this.iconButton(\n ind.visible ? 'eye' : 'eyeOff',\n ind.visible ? 'Hide' : 'Show',\n '',\n () => this.callbacks.onToggleIndicatorVisible?.(ind.instanceId, !ind.visible),\n ));\n }\n if (this.callbacks.onConfigureIndicator) {\n actions.appendChild(this.iconButton('settings', 'Indicator settings', '', () =>\n this.callbacks.onConfigureIndicator?.(ind.instanceId),\n ));\n }\n actions.appendChild(this.iconButton('trash', 'Remove indicator', 'tcw-tree-del', () =>\n this.callbacks.onRemoveIndicator(ind.instanceId),\n ));\n row.appendChild(actions);\n this.indicatorsEl.appendChild(row);\n }\n }\n\n private renderDrawings(drawings: ObjectTreeDrawing[]): void {\n this.drawingsEl.replaceChildren();\n if (drawings.length === 0) {\n this.drawingsEl.appendChild(this.emptyRow('No drawings'));\n return;\n }\n for (const d of drawings) {\n const row = this.row(d.label);\n if (!d.visible) row.classList.add('tcw-tree-hidden');\n\n const actions = document.createElement('div');\n actions.className = 'tcw-tree-actions';\n actions.appendChild(this.iconButton(\n d.visible ? 'eye' : 'eyeOff',\n d.visible ? 'Hide' : 'Show',\n '',\n () => this.callbacks.onToggleDrawingVisible(d.id, !d.visible),\n ));\n actions.appendChild(this.iconButton(\n d.locked ? 'lock' : 'unlock',\n d.locked ? 'Unlock' : 'Lock',\n d.locked ? 'tcw-tree-on' : '',\n () => this.callbacks.onToggleDrawingLocked(d.id, !d.locked),\n ));\n actions.appendChild(this.iconButton('trash', 'Remove drawing', 'tcw-tree-del', () =>\n this.callbacks.onRemoveDrawing(d.id),\n ));\n row.appendChild(actions);\n this.drawingsEl.appendChild(row);\n }\n }\n\n private renderCompares(compares: ObjectTreeCompare[]): void {\n if (!this.compareEl) return;\n this.compareEl.replaceChildren();\n if (compares.length === 0) {\n this.compareEl.appendChild(this.emptyRow('No comparisons'));\n return;\n }\n for (const c of compares) {\n const row = this.row(c.label);\n const dot = document.createElement('span');\n dot.className = 'tcw-tree-dot';\n dot.style.background = c.color;\n row.insertBefore(dot, row.firstChild);\n if (this.callbacks.onRemoveCompare) {\n row.appendChild(this.iconButton('trash', 'Remove comparison', 'tcw-tree-del', () =>\n this.callbacks.onRemoveCompare?.(c.id),\n ));\n }\n this.compareEl.appendChild(row);\n }\n }\n\n private row(label: string): HTMLDivElement {\n const row = document.createElement('div');\n row.className = 'tcw-tree-row';\n const name = document.createElement('span');\n name.className = 'tcw-tree-name';\n name.textContent = label;\n name.title = label;\n row.appendChild(name);\n return row;\n }\n\n private emptyRow(text: string): HTMLDivElement {\n const el = document.createElement('div');\n el.className = 'tcw-tree-empty';\n el.textContent = text;\n return el;\n }\n\n private iconButton(icon: string, label: string, extraClass: string, onClick: () => void): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = `tcw-tree-btn ${extraClass}`.trim();\n btn.setAttribute('aria-label', label);\n btn.title = label;\n btn.innerHTML = createIcon(icon, 14);\n btn.addEventListener('click', onClick);\n return btn;\n }\n}\n\nconst DRAWING_TYPE_LABELS: Record<string, string> = {\n trendLine: 'Trend Line',\n ray: 'Ray',\n extendedLine: 'Extended Line',\n horizontalLine: 'Horizontal Line',\n verticalLine: 'Vertical Line',\n rectangle: 'Rectangle',\n ellipse: 'Ellipse',\n triangle: 'Triangle',\n arrow: 'Arrow',\n parallelChannel: 'Parallel Channel',\n regressionChannel: 'Regression Channel',\n pitchfork: 'Pitchfork',\n fibRetracement: 'Fib Retracement',\n fibExtension: 'Fib Extension',\n fibTimeZones: 'Fib Time Zones',\n gannBox: 'Gann Box',\n gannFan: 'Gann Fan',\n elliottWave: 'Elliott Wave',\n priceRange: 'Price Range',\n dateRange: 'Date Range',\n measure: 'Measure',\n textAnnotation: 'Text',\n anchoredVWAP: 'Anchored VWAP',\n volumeProfileRange: 'Volume Profile',\n};\n\n/** Human-readable label for a drawing type, falling back to the raw key. */\nexport function drawingTypeLabel(type: string): string {\n return DRAWING_TYPE_LABELS[type] ?? type;\n}\n","import { createIcon } from './icons.js';\n\nexport type IndicatorParamValue = number | string | boolean;\n\nexport interface IndicatorSettingsTarget {\n instanceId: string;\n name: string;\n /** Default config — defines the editable keys and their types. */\n defaults: Record<string, unknown>;\n /** Current values, overlaid on defaults. */\n params: Record<string, unknown>;\n}\n\nexport interface IndicatorSettingsCallbacks {\n onApply: (instanceId: string, params: Record<string, IndicatorParamValue>) => void;\n onClose: () => void;\n}\n\nconst HEX_RE = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;\n\nfunction titleCase(key: string): string {\n // camelCase / snake_case → \"Title Case\"\n return key\n .replace(/_/g, ' ')\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .replace(/^./, (c) => c.toUpperCase());\n}\n\n/**\n * Per-indicator parameter editor. Introspects the indicator's default config to\n * decide each control (number → stepper, boolean → toggle, hex string → color,\n * other string → text) and applies edits live via `onApply`.\n */\nexport class WidgetIndicatorSettings {\n private backdrop: HTMLDivElement;\n private modal: HTMLDivElement;\n private bodyEl: HTMLDivElement;\n private titleEl: HTMLHeadingElement;\n private callbacks: IndicatorSettingsCallbacks;\n private target: IndicatorSettingsTarget | null = null;\n private draft: Record<string, IndicatorParamValue> = {};\n\n constructor(host: HTMLElement, callbacks: IndicatorSettingsCallbacks) {\n this.callbacks = callbacks;\n\n this.backdrop = document.createElement('div');\n this.backdrop.className = 'tcw-modal-backdrop';\n this.backdrop.hidden = true;\n this.backdrop.addEventListener('click', (e) => {\n if (e.target === this.backdrop) this.close();\n });\n\n this.modal = document.createElement('div');\n this.modal.className = 'tcw-modal tcw-modal-narrow';\n\n const header = document.createElement('div');\n header.className = 'tcw-modal-header';\n this.titleEl = document.createElement('h3');\n this.titleEl.textContent = 'Indicator';\n const closeBtn = document.createElement('button');\n closeBtn.className = 'tcw-modal-close';\n closeBtn.setAttribute('aria-label', 'Close');\n closeBtn.innerHTML = createIcon('x', 16);\n closeBtn.addEventListener('click', () => this.close());\n header.appendChild(this.titleEl);\n header.appendChild(closeBtn);\n\n this.bodyEl = document.createElement('div');\n this.bodyEl.className = 'tcw-modal-body';\n\n const footer = document.createElement('div');\n footer.className = 'tcw-modal-footer';\n const resetBtn = document.createElement('button');\n resetBtn.className = 'tcw-reset-link';\n resetBtn.textContent = 'Reset to defaults';\n resetBtn.addEventListener('click', () => this.resetDefaults());\n const doneBtn = document.createElement('button');\n doneBtn.className = 'tcw-done-btn';\n doneBtn.textContent = 'Done';\n doneBtn.addEventListener('click', () => this.close());\n footer.appendChild(resetBtn);\n footer.appendChild(doneBtn);\n\n this.modal.appendChild(header);\n this.modal.appendChild(this.bodyEl);\n this.modal.appendChild(footer);\n this.backdrop.appendChild(this.modal);\n host.appendChild(this.backdrop);\n }\n\n open(target: IndicatorSettingsTarget): void {\n this.target = target;\n this.titleEl.textContent = `${target.name} settings`;\n this.draft = {};\n this.renderFields();\n this.backdrop.hidden = false;\n }\n\n close(): void {\n this.backdrop.hidden = true;\n this.target = null;\n this.callbacks.onClose();\n }\n\n isOpen(): boolean {\n return !this.backdrop.hidden;\n }\n\n destroy(): void {\n this.backdrop.remove();\n }\n\n private currentValue(key: string): IndicatorParamValue {\n if (key in this.draft) return this.draft[key];\n const cur = this.target?.params[key];\n const def = this.target?.defaults[key];\n const val = cur ?? def;\n return val as IndicatorParamValue;\n }\n\n private setValue(key: string, value: IndicatorParamValue): void {\n if (!this.target) return;\n this.draft[key] = value;\n this.callbacks.onApply(this.target.instanceId, { ...this.draft });\n }\n\n private resetDefaults(): void {\n if (!this.target) return;\n const reset: Record<string, IndicatorParamValue> = {};\n for (const [key, def] of Object.entries(this.target.defaults)) {\n reset[key] = def as IndicatorParamValue;\n }\n this.draft = reset;\n this.callbacks.onApply(this.target.instanceId, { ...reset });\n this.renderFields();\n }\n\n private renderFields(): void {\n this.bodyEl.replaceChildren();\n if (!this.target) return;\n\n const section = document.createElement('div');\n section.className = 'tcw-settings-section';\n\n const keys = Object.keys(this.target.defaults);\n if (keys.length === 0) {\n const empty = document.createElement('div');\n empty.className = 'tcw-settings-label';\n empty.textContent = 'This indicator has no adjustable parameters.';\n section.appendChild(empty);\n }\n\n for (const key of keys) {\n section.appendChild(this.fieldRow(key));\n }\n this.bodyEl.appendChild(section);\n }\n\n private fieldRow(key: string): HTMLDivElement {\n const row = document.createElement('div');\n row.className = 'tcw-settings-row';\n const label = document.createElement('span');\n label.className = 'tcw-settings-label';\n label.textContent = titleCase(key);\n row.appendChild(label);\n\n const value = this.currentValue(key);\n const defType = typeof (this.target?.defaults[key] ?? value);\n\n if (defType === 'boolean') {\n row.appendChild(this.toggleControl(key, Boolean(value)));\n } else if (defType === 'number') {\n row.appendChild(this.numberControl(key, Number(value)));\n } else if (typeof value === 'string' && HEX_RE.test(value)) {\n row.appendChild(this.colorControl(key, value));\n } else {\n row.appendChild(this.textControl(key, String(value ?? '')));\n }\n return row;\n }\n\n private toggleControl(key: string, value: boolean): HTMLButtonElement {\n const toggle = document.createElement('button');\n toggle.className = `tcw-toggle${value ? ' tcw-on' : ''}`;\n toggle.type = 'button';\n toggle.addEventListener('click', () => {\n const next = !toggle.classList.contains('tcw-on');\n toggle.classList.toggle('tcw-on', next);\n this.setValue(key, next);\n });\n return toggle;\n }\n\n private numberControl(key: string, value: number): HTMLInputElement {\n const input = document.createElement('input');\n input.type = 'number';\n input.className = 'tcw-indi-input';\n input.value = String(value);\n // Integer-looking defaults step by 1; fractional defaults step by 0.1.\n input.step = Number.isInteger(value) ? '1' : '0.1';\n input.addEventListener('change', () => {\n const n = Number(input.value);\n if (Number.isFinite(n)) this.setValue(key, n);\n });\n return input;\n }\n\n private colorControl(key: string, value: string): HTMLInputElement {\n const input = document.createElement('input');\n input.type = 'color';\n input.className = 'tcw-indi-color';\n input.value = value.length === 4 ? expandHex(value) : value;\n input.addEventListener('input', () => this.setValue(key, input.value));\n return input;\n }\n\n private textControl(key: string, value: string): HTMLInputElement {\n const input = document.createElement('input');\n input.type = 'text';\n input.className = 'tcw-indi-input';\n input.value = value;\n input.addEventListener('change', () => this.setValue(key, input.value));\n return input;\n }\n}\n\nfunction expandHex(short: string): string {\n // #abc → #aabbcc\n const r = short[1], g = short[2], b = short[3];\n return `#${r}${r}${g}${g}${b}${b}`;\n}\n","import type { DrawingStyle } from '@tradecanvas/commons';\n\nexport interface DrawingStyleTemplate {\n name: string;\n style: Partial<DrawingStyle>;\n}\n\n/** Minimal storage surface — satisfied by `localStorage` and easy to mock. */\nexport interface KeyValueStorage {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n}\n\nfunction defaultStorage(): KeyValueStorage | null {\n try {\n return typeof localStorage !== 'undefined' ? localStorage : null;\n } catch {\n return null;\n }\n}\n\nconst STYLE_KEYS: (keyof DrawingStyle)[] = [\n 'color', 'lineWidth', 'lineStyle', 'fillColor', 'fillOpacity', 'fontSize',\n];\n\n/** Keep only known style keys — guards against junk persisted by older builds. */\nfunction sanitizeStyle(raw: unknown): Partial<DrawingStyle> {\n if (!raw || typeof raw !== 'object') return {};\n const out: Partial<DrawingStyle> = {};\n const obj = raw as Record<string, unknown>;\n for (const key of STYLE_KEYS) {\n if (obj[key] !== undefined) (out as Record<string, unknown>)[key] = obj[key];\n }\n return out;\n}\n\n/**\n * Named drawing-style presets, persisted to a key-value store. Templates are\n * upserted by name (case-sensitive) and ordered most-recently-saved last.\n */\nexport class DrawingTemplateStore {\n private templates: DrawingStyleTemplate[] = [];\n\n constructor(\n private storageKey = 'tcw:draw-templates',\n private storage: KeyValueStorage | null = defaultStorage(),\n ) {\n this.load();\n }\n\n list(): DrawingStyleTemplate[] {\n return this.templates.map((t) => ({ name: t.name, style: { ...t.style } }));\n }\n\n get(name: string): DrawingStyleTemplate | null {\n const t = this.templates.find((x) => x.name === name);\n return t ? { name: t.name, style: { ...t.style } } : null;\n }\n\n /** Insert or replace a template by name. */\n save(name: string, style: Partial<DrawingStyle>): void {\n const trimmed = name.trim();\n if (!trimmed) return;\n const clean = sanitizeStyle(style);\n this.templates = this.templates.filter((t) => t.name !== trimmed);\n this.templates.push({ name: trimmed, style: clean });\n this.persist();\n }\n\n remove(name: string): void {\n const next = this.templates.filter((t) => t.name !== name);\n if (next.length === this.templates.length) return;\n this.templates = next;\n this.persist();\n }\n\n clear(): void {\n this.templates = [];\n this.persist();\n }\n\n private load(): void {\n if (!this.storage) return;\n try {\n const raw = this.storage.getItem(this.storageKey);\n if (!raw) return;\n const parsed = JSON.parse(raw);\n if (!Array.isArray(parsed)) return;\n this.templates = parsed\n .filter((t) => t && typeof t.name === 'string')\n .map((t) => ({ name: t.name, style: sanitizeStyle(t.style) }));\n } catch {\n // Corrupt or unavailable storage — start empty.\n }\n }\n\n private persist(): void {\n if (!this.storage) return;\n try {\n this.storage.setItem(this.storageKey, JSON.stringify(this.templates));\n } catch {\n // Storage full or blocked — keep the in-memory copy.\n }\n }\n}\n","import type { DrawingStyle } from '@tradecanvas/commons';\nimport { createIcon } from './icons.js';\nimport { DrawingTemplateStore } from './DrawingTemplateStore.js';\n\nexport interface DrawingStyleCallbacks {\n /** Apply a style change to the active (next) drawing and the selected one. */\n onStyleChange: (style: Partial<DrawingStyle>) => void;\n /** Current active drawing style, for seeding controls and saving templates. */\n getStyle: () => DrawingStyle;\n}\n\nconst SWATCHES = ['#2962ff', '#089981', '#f23645', '#ff9800', '#ab47bc', '#26c6da', '#ffffff', '#787b86'];\nconst WIDTHS = [1, 2, 3, 4];\nconst LINE_STYLES: DrawingStyle['lineStyle'][] = ['solid', 'dashed', 'dotted'];\n\n/**\n * Drawing style popover — pick colour, line width, and line style for the next\n * drawing (and the selected one), plus save/apply named style templates\n * persisted via `DrawingTemplateStore`.\n */\nexport class WidgetDrawingStyle {\n private el: HTMLDivElement;\n private templatesEl: HTMLDivElement;\n private nameInput: HTMLInputElement;\n private callbacks: DrawingStyleCallbacks;\n private store: DrawingTemplateStore;\n private open = false;\n\n constructor(host: HTMLElement, callbacks: DrawingStyleCallbacks, store: DrawingTemplateStore) {\n this.callbacks = callbacks;\n this.store = store;\n\n this.el = document.createElement('div');\n this.el.className = 'tcw-style-panel';\n this.el.hidden = true;\n\n const header = document.createElement('div');\n header.className = 'tcw-style-header';\n const title = document.createElement('span');\n title.textContent = 'Drawing Style';\n const closeBtn = document.createElement('button');\n closeBtn.type = 'button';\n closeBtn.className = 'tcw-style-close';\n closeBtn.setAttribute('aria-label', 'Close');\n closeBtn.innerHTML = createIcon('x', 14);\n closeBtn.addEventListener('click', () => this.close());\n header.appendChild(title);\n header.appendChild(closeBtn);\n this.el.appendChild(header);\n\n this.el.appendChild(this.colorRow());\n this.el.appendChild(this.widthRow());\n this.el.appendChild(this.lineStyleRow());\n\n // Templates\n const tmplHead = document.createElement('div');\n tmplHead.className = 'tcw-style-subhead';\n tmplHead.textContent = 'Templates';\n this.el.appendChild(tmplHead);\n\n const saveRow = document.createElement('div');\n saveRow.className = 'tcw-style-save';\n this.nameInput = document.createElement('input');\n this.nameInput.type = 'text';\n this.nameInput.placeholder = 'Template name';\n this.nameInput.className = 'tcw-style-name';\n const saveBtn = document.createElement('button');\n saveBtn.type = 'button';\n saveBtn.className = 'tcw-style-savebtn';\n saveBtn.innerHTML = `${createIcon('plus', 13)}<span>Save</span>`;\n saveBtn.addEventListener('click', () => this.saveTemplate());\n saveRow.appendChild(this.nameInput);\n saveRow.appendChild(saveBtn);\n this.el.appendChild(saveRow);\n\n this.templatesEl = document.createElement('div');\n this.templatesEl.className = 'tcw-style-templates';\n this.el.appendChild(this.templatesEl);\n\n host.appendChild(this.el);\n this.renderTemplates();\n }\n\n isOpen(): boolean {\n return this.open;\n }\n\n toggle(): void {\n this.open ? this.close() : this.openPanel();\n }\n\n openPanel(): void {\n this.open = true;\n this.el.hidden = false;\n this.syncActiveControls();\n this.renderTemplates();\n }\n\n close(): void {\n this.open = false;\n this.el.hidden = true;\n }\n\n destroy(): void {\n this.el.remove();\n }\n\n private colorRow(): HTMLDivElement {\n const row = document.createElement('div');\n row.className = 'tcw-style-row tcw-style-colors';\n for (const c of SWATCHES) {\n const sw = document.createElement('button');\n sw.type = 'button';\n sw.className = 'tcw-style-swatch';\n sw.style.background = c;\n sw.dataset.color = c;\n sw.setAttribute('aria-label', c);\n sw.addEventListener('click', () => this.applyStyle({ color: c }));\n row.appendChild(sw);\n }\n const picker = document.createElement('input');\n picker.type = 'color';\n picker.className = 'tcw-style-picker';\n picker.addEventListener('input', () => this.applyStyle({ color: picker.value }));\n row.appendChild(picker);\n return row;\n }\n\n private widthRow(): HTMLDivElement {\n const row = document.createElement('div');\n row.className = 'tcw-style-row tcw-style-widths';\n for (const w of WIDTHS) {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'tcw-style-width';\n btn.dataset.width = String(w);\n const bar = document.createElement('span');\n bar.style.height = `${w}px`;\n btn.appendChild(bar);\n btn.addEventListener('click', () => this.applyStyle({ lineWidth: w }));\n row.appendChild(btn);\n }\n return row;\n }\n\n private lineStyleRow(): HTMLDivElement {\n const row = document.createElement('div');\n row.className = 'tcw-style-row tcw-style-dashes';\n for (const ls of LINE_STYLES) {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'tcw-style-dash';\n btn.dataset.linestyle = ls;\n btn.textContent = ls === 'solid' ? '──' : ls === 'dashed' ? '╌╌' : '┄┄';\n btn.title = ls;\n btn.addEventListener('click', () => this.applyStyle({ lineStyle: ls }));\n row.appendChild(btn);\n }\n return row;\n }\n\n private applyStyle(patch: Partial<DrawingStyle>): void {\n this.callbacks.onStyleChange(patch);\n this.syncActiveControls();\n }\n\n /** Mark the controls matching the current active style. */\n private syncActiveControls(): void {\n const style = this.callbacks.getStyle();\n this.el.querySelectorAll<HTMLElement>('.tcw-style-swatch').forEach((sw) => {\n sw.classList.toggle('tcw-on', sw.dataset.color?.toLowerCase() === style.color?.toLowerCase());\n });\n this.el.querySelectorAll<HTMLElement>('.tcw-style-width').forEach((b) => {\n b.classList.toggle('tcw-on', Number(b.dataset.width) === style.lineWidth);\n });\n this.el.querySelectorAll<HTMLElement>('.tcw-style-dash').forEach((b) => {\n b.classList.toggle('tcw-on', b.dataset.linestyle === style.lineStyle);\n });\n }\n\n private saveTemplate(): void {\n const name = this.nameInput.value.trim();\n if (!name) return;\n this.store.save(name, this.callbacks.getStyle());\n this.nameInput.value = '';\n this.renderTemplates();\n }\n\n private renderTemplates(): void {\n this.templatesEl.replaceChildren();\n const templates = this.store.list();\n if (templates.length === 0) {\n const empty = document.createElement('div');\n empty.className = 'tcw-style-empty';\n empty.textContent = 'No saved templates';\n this.templatesEl.appendChild(empty);\n return;\n }\n for (const t of templates) {\n const row = document.createElement('div');\n row.className = 'tcw-style-template';\n\n const apply = document.createElement('button');\n apply.type = 'button';\n apply.className = 'tcw-style-apply';\n const dot = document.createElement('span');\n dot.className = 'tcw-style-tdot';\n dot.style.background = (t.style.color as string) ?? 'var(--tcw-text-muted)';\n const label = document.createElement('span');\n label.textContent = t.name;\n apply.appendChild(dot);\n apply.appendChild(label);\n apply.addEventListener('click', () => {\n this.callbacks.onStyleChange({ ...t.style });\n this.syncActiveControls();\n });\n\n const del = document.createElement('button');\n del.type = 'button';\n del.className = 'tcw-style-tdel';\n del.setAttribute('aria-label', 'Delete template');\n del.innerHTML = createIcon('trash', 13);\n del.addEventListener('click', () => {\n this.store.remove(t.name);\n this.renderTemplates();\n });\n\n row.appendChild(apply);\n row.appendChild(del);\n this.templatesEl.appendChild(row);\n }\n }\n}\n","import type { KeyValueStorage } from './DrawingTemplateStore.js';\n\nfunction defaultStorage(): KeyValueStorage | null {\n try {\n return typeof localStorage !== 'undefined' ? localStorage : null;\n } catch {\n return null;\n }\n}\n\n/**\n * An ordered, de-duplicated set of pinned drawing-tool ids, persisted to a\n * key-value store. Order is insertion order (most-recently-pinned last).\n */\nexport class DrawingFavoritesStore {\n private favorites: string[] = [];\n\n constructor(\n private storageKey = 'tcw:draw-favorites',\n private storage: KeyValueStorage | null = defaultStorage(),\n ) {\n this.load();\n }\n\n list(): string[] {\n return [...this.favorites];\n }\n\n has(tool: string): boolean {\n return this.favorites.includes(tool);\n }\n\n add(tool: string): void {\n if (!tool || this.favorites.includes(tool)) return;\n this.favorites = [...this.favorites, tool];\n this.persist();\n }\n\n remove(tool: string): void {\n if (!this.favorites.includes(tool)) return;\n this.favorites = this.favorites.filter((t) => t !== tool);\n this.persist();\n }\n\n /** Toggle a tool's pinned state. Returns the new state (true = pinned). */\n toggle(tool: string): boolean {\n if (this.has(tool)) {\n this.remove(tool);\n return false;\n }\n this.add(tool);\n return true;\n }\n\n /** Seed the favorites only when none are stored yet (first run). */\n seedDefaults(tools: string[]): void {\n if (this.favorites.length > 0) return;\n this.favorites = [...new Set(tools.filter(Boolean))];\n this.persist();\n }\n\n private load(): void {\n if (!this.storage) return;\n try {\n const raw = this.storage.getItem(this.storageKey);\n if (!raw) return;\n const parsed = JSON.parse(raw);\n if (Array.isArray(parsed)) {\n this.favorites = [...new Set(parsed.filter((t) => typeof t === 'string'))];\n }\n } catch {\n // Corrupt or unavailable — start empty.\n }\n }\n\n private persist(): void {\n if (!this.storage) return;\n try {\n this.storage.setItem(this.storageKey, JSON.stringify(this.favorites));\n } catch {\n // Storage full or blocked — keep the in-memory copy.\n }\n }\n}\n","import { createIcon } from './icons.js';\n\nexport interface BracketBarCallbacks {\n onConfirm: () => void;\n onCancel: () => void;\n}\n\n/**\n * Floating confirm/cancel bar shown while a bracket order is being placed.\n * The live entry / SL / TP numbers are drawn on the chart canvas; this bar\n * just carries the commit and discard actions (also bound to Enter / Esc).\n */\nexport class WidgetBracketBar {\n private el: HTMLDivElement;\n private labelEl: HTMLSpanElement;\n private callbacks: BracketBarCallbacks;\n private visible = false;\n\n constructor(host: HTMLElement, callbacks: BracketBarCallbacks) {\n this.callbacks = callbacks;\n\n this.el = document.createElement('div');\n this.el.className = 'tcw-bracket-bar';\n this.el.hidden = true;\n\n this.labelEl = document.createElement('span');\n this.labelEl.className = 'tcw-bracket-label';\n this.el.appendChild(this.labelEl);\n\n const hint = document.createElement('span');\n hint.className = 'tcw-bracket-hint';\n hint.textContent = 'drag lines to adjust';\n this.el.appendChild(hint);\n\n const cancel = document.createElement('button');\n cancel.type = 'button';\n cancel.className = 'tcw-bracket-cancel';\n cancel.innerHTML = `${createIcon('x', 14)}<span>Cancel</span>`;\n cancel.addEventListener('click', () => this.callbacks.onCancel());\n\n const confirm = document.createElement('button');\n confirm.type = 'button';\n confirm.className = 'tcw-bracket-confirm';\n confirm.innerHTML = `${createIcon('check', 14)}<span>Place</span>`;\n confirm.addEventListener('click', () => this.callbacks.onConfirm());\n\n this.el.appendChild(cancel);\n this.el.appendChild(confirm);\n host.appendChild(this.el);\n }\n\n show(side: 'buy' | 'sell'): void {\n this.visible = true;\n this.labelEl.textContent = side === 'buy' ? 'Long bracket' : 'Short bracket';\n this.labelEl.dataset.side = side;\n this.el.hidden = false;\n }\n\n hide(): void {\n this.visible = false;\n this.el.hidden = true;\n }\n\n isVisible(): boolean {\n return this.visible;\n }\n\n destroy(): void {\n this.el.remove();\n }\n}\n","export interface AlertNotifyOptions {\n /** Play a sound on trigger. `true` = built-in beep, string = audio URL. Default `false`. */\n sound?: boolean | string;\n /** Show a desktop notification (requests permission on first use). Default `false`. */\n desktop?: boolean;\n /** Title for desktop notifications. Default `'Price alert'`. */\n title?: string;\n}\n\n/** True when the Notification API is present and not denied. */\nexport function canRequestNotifications(): boolean {\n return typeof Notification !== 'undefined' && Notification.permission !== 'denied';\n}\n\n/**\n * Plays a sound and/or raises a desktop notification when a price alert fires.\n * Browser-API heavy by nature — every entry point is guarded so it degrades to\n * a no-op in SSR, unsupported browsers, or when permission is denied.\n */\nexport class AlertNotifier {\n private options: AlertNotifyOptions;\n private audioCtx: AudioContext | null = null;\n private audioEl: HTMLAudioElement | null = null;\n private permissionAsked = false;\n\n constructor(options: AlertNotifyOptions = {}) {\n this.options = options;\n if (typeof options.sound === 'string') {\n try {\n this.audioEl = new Audio(options.sound);\n this.audioEl.preload = 'auto';\n } catch {\n this.audioEl = null;\n }\n }\n // Request notification permission up front so the first alert isn't silent.\n if (options.desktop) this.ensurePermission();\n }\n\n setOptions(options: AlertNotifyOptions): void {\n this.options = { ...this.options, ...options };\n }\n\n /** Fire the configured notifications for a triggered alert. */\n notify(message: string): void {\n if (this.options.sound) this.playSound();\n if (this.options.desktop) this.showDesktop(message);\n }\n\n private playSound(): void {\n if (this.audioEl) {\n this.audioEl.currentTime = 0;\n void this.audioEl.play().catch(() => {});\n return;\n }\n this.beep();\n }\n\n /** A short two-tone beep via Web Audio — no asset required. */\n private beep(): void {\n try {\n const Ctx = window.AudioContext ?? (window as unknown as { webkitAudioContext?: typeof AudioContext }).webkitAudioContext;\n if (!Ctx) return;\n if (!this.audioCtx) this.audioCtx = new Ctx();\n const ctx = this.audioCtx;\n const now = ctx.currentTime;\n const gain = ctx.createGain();\n gain.gain.setValueAtTime(0.0001, now);\n gain.gain.exponentialRampToValueAtTime(0.2, now + 0.01);\n gain.gain.exponentialRampToValueAtTime(0.0001, now + 0.35);\n gain.connect(ctx.destination);\n const osc = ctx.createOscillator();\n osc.type = 'sine';\n osc.frequency.setValueAtTime(880, now);\n osc.frequency.setValueAtTime(1320, now + 0.16);\n osc.connect(gain);\n osc.start(now);\n osc.stop(now + 0.36);\n } catch {\n // Audio unavailable or blocked by autoplay policy — silent.\n }\n }\n\n private ensurePermission(): void {\n if (this.permissionAsked) return;\n this.permissionAsked = true;\n if (typeof Notification === 'undefined') return;\n if (Notification.permission === 'default') {\n void Notification.requestPermission().catch(() => {});\n }\n }\n\n private showDesktop(message: string): void {\n if (typeof Notification === 'undefined') return;\n if (Notification.permission !== 'granted') {\n this.ensurePermission();\n return;\n }\n try {\n new Notification(this.options.title ?? 'Price alert', { body: message });\n } catch {\n // Some browsers throw if not invoked from a user gesture — ignore.\n }\n }\n\n destroy(): void {\n try {\n void this.audioCtx?.close();\n } catch {\n // ignore\n }\n this.audioCtx = null;\n this.audioEl = null;\n }\n}\n","import type { DepthData } from '@tradecanvas/commons';\n\nexport interface LadderRow {\n price: number;\n bidVolume: number;\n askVolume: number;\n}\n\nexport interface LadderModel {\n /** Rows ordered high → low price (asks on top, bids below). */\n rows: LadderRow[];\n /** Largest single-side volume across the shown rows (for bar scaling). */\n maxVolume: number;\n /** Midpoint between best bid and best ask, or null if a side is empty. */\n mid: number | null;\n}\n\n/**\n * Build a depth-of-market ladder from an order book: the best `maxLevels` asks\n * (lowest prices) and best `maxLevels` bids (highest prices), merged into rows\n * ordered high→low. A price present on both sides is merged into one row.\n */\nexport function buildLadderRows(data: DepthData, maxLevels = 12): LadderModel {\n const asks = [...data.asks].sort((a, b) => a.price - b.price).slice(0, maxLevels);\n const bids = [...data.bids].sort((a, b) => b.price - a.price).slice(0, maxLevels);\n\n const bestAsk = asks.length > 0 ? asks[0].price : null;\n const bestBid = bids.length > 0 ? bids[0].price : null;\n const mid = bestAsk !== null && bestBid !== null ? (bestAsk + bestBid) / 2 : null;\n\n const byPrice = new Map<number, LadderRow>();\n const rowAt = (price: number): LadderRow => {\n let row = byPrice.get(price);\n if (!row) {\n row = { price, bidVolume: 0, askVolume: 0 };\n byPrice.set(price, row);\n }\n return row;\n };\n for (const a of asks) rowAt(a.price).askVolume += a.volume;\n for (const b of bids) rowAt(b.price).bidVolume += b.volume;\n\n const rows = [...byPrice.values()].sort((a, b) => b.price - a.price);\n let maxVolume = 0;\n for (const r of rows) maxVolume = Math.max(maxVolume, r.bidVolume, r.askVolume);\n\n return { rows, maxVolume, mid };\n}\n","import type { DepthData } from '@tradecanvas/commons';\nimport { createIcon } from './icons.js';\nimport { buildLadderRows, type LadderModel } from './ladderRows.js';\n\nexport interface DepthLadderCallbacks {\n /** Buy at `price` (clicked an ask cell) or sell at `price` (clicked a bid cell). */\n onTrade: (side: 'buy' | 'sell', price: number) => void;\n formatPrice: (price: number) => string;\n}\n\n/**\n * Depth-of-market ladder (DOM). Renders the order book as price rows with bid\n * and ask size columns; clicking an ask cell buys at that price, a bid cell\n * sells. Fed by `setData(depth)`; the bar widths scale to the largest visible\n * size.\n */\nexport class WidgetDepthLadder {\n private el: HTMLDivElement;\n private bodyEl: HTMLDivElement;\n private callbacks: DepthLadderCallbacks;\n private open = false;\n private levels: number;\n\n constructor(host: HTMLElement, callbacks: DepthLadderCallbacks, levels = 12) {\n this.callbacks = callbacks;\n this.levels = levels;\n\n this.el = document.createElement('div');\n this.el.className = 'tcw-ladder';\n this.el.hidden = true;\n\n const header = document.createElement('div');\n header.className = 'tcw-ladder-header';\n const title = document.createElement('span');\n title.textContent = 'Depth Ladder';\n const closeBtn = document.createElement('button');\n closeBtn.type = 'button';\n closeBtn.className = 'tcw-ladder-close';\n closeBtn.setAttribute('aria-label', 'Close');\n closeBtn.innerHTML = createIcon('x', 14);\n closeBtn.addEventListener('click', () => this.close());\n header.appendChild(title);\n header.appendChild(closeBtn);\n this.el.appendChild(header);\n\n const cols = document.createElement('div');\n cols.className = 'tcw-ladder-cols';\n cols.innerHTML = '<span>Bid</span><span>Price</span><span>Ask</span>';\n this.el.appendChild(cols);\n\n this.bodyEl = document.createElement('div');\n this.bodyEl.className = 'tcw-ladder-body';\n this.el.appendChild(this.bodyEl);\n\n host.appendChild(this.el);\n }\n\n isOpen(): boolean {\n return this.open;\n }\n\n toggle(): void {\n this.open ? this.close() : this.openPanel();\n }\n\n openPanel(): void {\n this.open = true;\n this.el.hidden = false;\n }\n\n close(): void {\n this.open = false;\n this.el.hidden = true;\n }\n\n setData(depth: DepthData | null): void {\n if (!depth) {\n this.renderEmpty();\n return;\n }\n this.render(buildLadderRows(depth, this.levels));\n }\n\n destroy(): void {\n this.el.remove();\n }\n\n private renderEmpty(): void {\n this.bodyEl.replaceChildren();\n const empty = document.createElement('div');\n empty.className = 'tcw-ladder-empty';\n empty.textContent = 'No order-book data';\n this.bodyEl.appendChild(empty);\n }\n\n private render(model: LadderModel): void {\n this.bodyEl.replaceChildren();\n if (model.rows.length === 0) {\n this.renderEmpty();\n return;\n }\n const inv = model.maxVolume > 0 ? 1 / model.maxVolume : 0;\n\n for (const row of model.rows) {\n const isAsk = row.askVolume > 0;\n const tr = document.createElement('div');\n tr.className = 'tcw-ladder-row';\n\n // Bid cell (click → sell at price)\n const bid = document.createElement('button');\n bid.type = 'button';\n bid.className = 'tcw-ladder-cell tcw-ladder-bid';\n if (row.bidVolume > 0) {\n bid.textContent = formatSize(row.bidVolume);\n bid.style.setProperty('--w', `${(row.bidVolume * inv * 100).toFixed(1)}%`);\n bid.title = `Sell @ ${this.callbacks.formatPrice(row.price)}`;\n bid.addEventListener('click', () => this.callbacks.onTrade('sell', row.price));\n } else {\n bid.disabled = true;\n }\n\n const price = document.createElement('div');\n price.className = `tcw-ladder-price ${isAsk ? 'tcw-ask' : 'tcw-bid'}`;\n price.textContent = this.callbacks.formatPrice(row.price);\n\n // Ask cell (click → buy at price)\n const ask = document.createElement('button');\n ask.type = 'button';\n ask.className = 'tcw-ladder-cell tcw-ladder-ask';\n if (row.askVolume > 0) {\n ask.textContent = formatSize(row.askVolume);\n ask.style.setProperty('--w', `${(row.askVolume * inv * 100).toFixed(1)}%`);\n ask.title = `Buy @ ${this.callbacks.formatPrice(row.price)}`;\n ask.addEventListener('click', () => this.callbacks.onTrade('buy', row.price));\n } else {\n ask.disabled = true;\n }\n\n tr.appendChild(bid);\n tr.appendChild(price);\n tr.appendChild(ask);\n this.bodyEl.appendChild(tr);\n }\n }\n}\n\nfunction formatSize(v: number): string {\n if (v >= 1000) return (v / 1000).toFixed(1) + 'k';\n if (v >= 1) return v.toFixed(2).replace(/\\.00$/, '');\n return v.toPrecision(2);\n}\n","import { createIcon } from './icons.js';\n\nexport interface DataWindowIndicator {\n name: string;\n values: { key: string; value: number }[];\n}\n\nexport interface DataWindowModel {\n ohlc: { open: number; high: number; low: number; close: number; volume: number } | null;\n change: number;\n changePct: number;\n indicators: DataWindowIndicator[];\n}\n\nexport interface DataWindowCallbacks {\n formatPrice: (price: number) => string;\n}\n\n/**\n * Data Window — a floating readout of the exact O/H/L/C/V, change, and every\n * active indicator value at the hovered bar. Updated from `crosshairMove`.\n */\nexport class WidgetDataWindow {\n private el: HTMLDivElement;\n private bodyEl: HTMLDivElement;\n private callbacks: DataWindowCallbacks;\n private open = false;\n\n constructor(host: HTMLElement, callbacks: DataWindowCallbacks) {\n this.callbacks = callbacks;\n\n this.el = document.createElement('div');\n this.el.className = 'tcw-datawin';\n this.el.hidden = true;\n\n const header = document.createElement('div');\n header.className = 'tcw-datawin-header';\n const title = document.createElement('span');\n title.textContent = 'Data Window';\n const closeBtn = document.createElement('button');\n closeBtn.type = 'button';\n closeBtn.className = 'tcw-datawin-close';\n closeBtn.setAttribute('aria-label', 'Close');\n closeBtn.innerHTML = createIcon('x', 14);\n closeBtn.addEventListener('click', () => this.close());\n header.appendChild(title);\n header.appendChild(closeBtn);\n this.el.appendChild(header);\n\n this.bodyEl = document.createElement('div');\n this.bodyEl.className = 'tcw-datawin-body';\n this.el.appendChild(this.bodyEl);\n\n host.appendChild(this.el);\n }\n\n isOpen(): boolean {\n return this.open;\n }\n\n toggle(): void {\n this.open ? this.close() : this.openPanel();\n }\n\n openPanel(): void {\n this.open = true;\n this.el.hidden = false;\n }\n\n close(): void {\n this.open = false;\n this.el.hidden = true;\n }\n\n destroy(): void {\n this.el.remove();\n }\n\n render(model: DataWindowModel): void {\n if (!this.open) return;\n this.bodyEl.replaceChildren();\n\n if (!model.ohlc) {\n const empty = document.createElement('div');\n empty.className = 'tcw-datawin-empty';\n empty.textContent = 'Hover the chart';\n this.bodyEl.appendChild(empty);\n return;\n }\n\n const fp = this.callbacks.formatPrice;\n const o = model.ohlc;\n this.bodyEl.appendChild(this.row('Open', fp(o.open)));\n this.bodyEl.appendChild(this.row('High', fp(o.high)));\n this.bodyEl.appendChild(this.row('Low', fp(o.low)));\n this.bodyEl.appendChild(this.row('Close', fp(o.close)));\n const tone = model.change > 0 ? 'up' : model.change < 0 ? 'down' : '';\n const sign = model.change > 0 ? '+' : '';\n this.bodyEl.appendChild(this.row('Change', `${sign}${fp(model.change)} (${sign}${model.changePct.toFixed(2)}%)`, tone));\n this.bodyEl.appendChild(this.row('Volume', formatVolume(o.volume)));\n\n for (const ind of model.indicators) {\n const head = document.createElement('div');\n head.className = 'tcw-datawin-sub';\n head.textContent = ind.name;\n this.bodyEl.appendChild(head);\n for (const v of ind.values) {\n this.bodyEl.appendChild(this.row(v.key, formatNumber(v.value)));\n }\n }\n }\n\n private row(label: string, value: string, tone = ''): HTMLDivElement {\n const row = document.createElement('div');\n row.className = 'tcw-datawin-row';\n const l = document.createElement('span');\n l.className = 'tcw-datawin-label';\n l.textContent = label;\n const v = document.createElement('span');\n v.className = `tcw-datawin-value${tone ? ` tcw-${tone}` : ''}`;\n v.textContent = value;\n row.appendChild(l);\n row.appendChild(v);\n return row;\n }\n}\n\nfunction formatNumber(v: number): string {\n if (!Number.isFinite(v)) return '—';\n const abs = Math.abs(v);\n if (abs >= 1000) return v.toFixed(2);\n if (abs >= 1) return v.toFixed(4);\n return v.toPrecision(4);\n}\n\nfunction formatVolume(v: number): string {\n if (v >= 1_000_000_000) return (v / 1_000_000_000).toFixed(2) + 'B';\n if (v >= 1_000_000) return (v / 1_000_000).toFixed(2) + 'M';\n if (v >= 1_000) return (v / 1_000).toFixed(2) + 'K';\n return v.toFixed(0);\n}\n","import type { ChartType, TimeFrame, DrawingState, PriceScaleMode } from '@tradecanvas/commons';\n\nexport interface ShareableIndicator {\n id: string;\n params: Record<string, number | string | boolean>;\n}\n\nexport interface ShareableWidgetState {\n v: 1;\n symbol: string;\n timeframe: TimeFrame;\n chartType: ChartType;\n scaleMode: PriceScaleMode;\n indicators: ShareableIndicator[];\n drawings: DrawingState[];\n}\n\ninterface NodeBufferCtor {\n from(input: string, encoding: string): { toString(encoding: string): string };\n}\nconst nodeBuffer = (globalThis as { Buffer?: NodeBufferCtor }).Buffer;\n\nfunction utf8ToBase64(str: string): string {\n if (nodeBuffer) return nodeBuffer.from(str, 'utf8').toString('base64');\n const bytes = new TextEncoder().encode(str);\n let bin = '';\n for (const b of bytes) bin += String.fromCharCode(b);\n return btoa(bin);\n}\n\nfunction base64ToUtf8(b64: string): string {\n if (nodeBuffer) return nodeBuffer.from(b64, 'base64').toString('utf8');\n const bin = atob(b64);\n const bytes = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i);\n return new TextDecoder().decode(bytes);\n}\n\nfunction toBase64Url(b64: string): string {\n return b64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\nfunction fromBase64Url(s: string): string {\n const b64 = s.replace(/-/g, '+').replace(/_/g, '/');\n const pad = b64.length % 4 === 0 ? '' : '='.repeat(4 - (b64.length % 4));\n return b64 + pad;\n}\n\n/** Encode a shareable widget state to a compact, URL-safe string. */\nexport function encodeWidgetState(state: ShareableWidgetState): string {\n return toBase64Url(utf8ToBase64(JSON.stringify(state)));\n}\n\n/**\n * Decode a shareable-state string. Returns null for anything malformed or of an\n * unknown version — callers should treat null as \"ignore and keep current view\".\n */\nexport function decodeWidgetState(encoded: string): ShareableWidgetState | null {\n if (!encoded) return null;\n try {\n const json = base64ToUtf8(fromBase64Url(encoded));\n const obj = JSON.parse(json);\n if (!obj || obj.v !== 1 || typeof obj.symbol !== 'string') return null;\n return {\n v: 1,\n symbol: obj.symbol,\n timeframe: obj.timeframe,\n chartType: obj.chartType,\n scaleMode: obj.scaleMode ?? 'regular',\n indicators: Array.isArray(obj.indicators) ? obj.indicators : [],\n drawings: Array.isArray(obj.drawings) ? obj.drawings : [],\n };\n } catch {\n return null;\n }\n}\n\nconst HASH_KEY = 'tcw';\n\n/** Read a `#tcw=<encoded>` fragment from a URL hash, or null. */\nexport function readShareHash(hash: string): string | null {\n const clean = hash.startsWith('#') ? hash.slice(1) : hash;\n for (const part of clean.split('&')) {\n const eq = part.indexOf('=');\n if (eq > 0 && part.slice(0, eq) === HASH_KEY) return decodeURIComponent(part.slice(eq + 1));\n }\n return null;\n}\n\n/** Build a shareable URL by replacing the `tcw` hash param on `base`. */\nexport function buildShareUrl(base: string, encoded: string): string {\n const [withoutHash] = base.split('#');\n return `${withoutHash}#${HASH_KEY}=${encoded}`;\n}\n","import type { ChartType, DrawingToolType, Theme, TimeFrame } from '@tradecanvas/commons';\nimport { Chart } from '../Chart.js';\nimport { DARK_THEME, LIGHT_THEME } from '@tradecanvas/commons';\nimport type { ChartWidgetOptions, WidgetState, ChartSettingsState } from './types.js';\nimport { TIMEFRAMES, CHART_TYPES, INDICATORS, POPULAR_INDICATORS, DRAWING_TOOL_GROUPS, DEFAULT_SYMBOLS, DEFAULT_SETTINGS } from './widgetConfig.js';\nimport { injectWidgetStyles, removeWidgetStyles } from './WidgetStyles.js';\nimport { WidgetToolbar } from './WidgetToolbar.js';\nimport { WidgetDrawingSidebar } from './WidgetDrawingSidebar.js';\nimport { WidgetSettings } from './WidgetSettings.js';\nimport { WidgetStatusBar } from './WidgetStatusBar.js';\nimport { WidgetCommandPalette } from './WidgetCommandPalette.js';\nimport { WidgetSymbolSearch } from './WidgetSymbolSearch.js';\nimport { WidgetHotkeySheet } from './WidgetHotkeySheet.js';\nimport { WidgetReplayBar } from './WidgetReplayBar.js';\nimport { WidgetWatchlist, type WatchlistEntry } from './WidgetWatchlist.js';\nimport { WidgetAlertsPanel } from './WidgetAlertsPanel.js';\nimport { WidgetObjectTree, drawingTypeLabel } from './WidgetObjectTree.js';\nimport { WidgetIndicatorSettings } from './WidgetIndicatorSettings.js';\nimport { WidgetDrawingStyle } from './WidgetDrawingStyle.js';\nimport { DrawingTemplateStore } from './DrawingTemplateStore.js';\nimport { DrawingFavoritesStore } from './DrawingFavoritesStore.js';\nimport { WidgetBracketBar } from './WidgetBracketBar.js';\nimport { AlertNotifier } from './AlertNotifier.js';\nimport { WidgetDepthLadder } from './WidgetDepthLadder.js';\nimport { WidgetDataWindow, type DataWindowModel } from './WidgetDataWindow.js';\nimport type { DepthData } from '@tradecanvas/commons';\nimport { encodeWidgetState, decodeWidgetState, readShareHash, buildShareUrl } from './widgetShareState.js';\nimport { DragDropImporter, resampleOHLCV, inferTimeframeMs } from '../io/index.js';\nimport type { DataSeries } from '@tradecanvas/commons';\nimport { timeframeToMs } from '@tradecanvas/commons';\nimport type { CommandItem } from './WidgetCommandPalette.js';\n\n/** Distinct line colors for comparison overlays, cycled by add order. */\nconst COMPARE_COLORS = ['#f7931a', '#627eea', '#26a17b', '#e84142', '#8247e5', '#f3ba2f'];\n\nexport class ChartWidget {\n private chart: Chart;\n private state: WidgetState;\n private toolbar: WidgetToolbar | null = null;\n private sidebar: WidgetDrawingSidebar | null = null;\n private settings: WidgetSettings | null = null;\n private statusBar: WidgetStatusBar | null = null;\n private commandPalette: WidgetCommandPalette | null = null;\n private symbolSearch: WidgetSymbolSearch | null = null;\n private hotkeySheet: WidgetHotkeySheet | null = null;\n private replayBar: WidgetReplayBar | null = null;\n private dragDrop: DragDropImporter | null = null;\n private alertsPanel: WidgetAlertsPanel | null = null;\n private objectTree: WidgetObjectTree | null = null;\n private indicatorSettings: WidgetIndicatorSettings | null = null;\n private drawingStyle: WidgetDrawingStyle | null = null;\n private bracketBar: WidgetBracketBar | null = null;\n private alertNotifier: AlertNotifier | null = null;\n private depthLadder: WidgetDepthLadder | null = null;\n private dataWindow: WidgetDataWindow | null = null;\n private lastHoverIndex: number | null = null;\n private favoritesStore = new DrawingFavoritesStore();\n private watchlist: WidgetWatchlist | null = null;\n private watchlistSparkBuffer = new Map<string, number[]>();\n private sessionRefPrice: number | null = null;\n private watchlistInterval: ReturnType<typeof setInterval> | null = null;\n private replayOriginalData: DataSeries | null = null;\n private replayPollInterval: ReturnType<typeof setInterval> | null = null;\n private replaySpeed = 5;\n private layoutKeyPrefix: string | null = null;\n private layoutDebounceMs = 1500;\n private activeLayoutKey: string | null = null;\n private root: HTMLDivElement;\n private chartContainer: HTMLDivElement;\n private destroyed = false;\n private options: ChartWidgetOptions;\n private symbols: string[];\n private settingsState: ChartSettingsState;\n private adapter: import('@tradecanvas/commons').DataAdapter | null = null;\n private boundGlobalKeydown: ((e: KeyboardEvent) => void) | null = null;\n // Finest-resolution series the widget has seen. When no live adapter is\n // attached, switching to a coarser timeframe resamples from this base\n // instead of refetching. See `setData` / `applyTimeframeData`.\n private baseSeries: DataSeries | null = null;\n private baseTimeframeMs = 0;\n private compares: { id: string; symbol: string; color: string }[] = [];\n\n constructor(container: HTMLElement, options: ChartWidgetOptions = {}) {\n this.options = options;\n this.symbols = options.symbols ?? DEFAULT_SYMBOLS;\n this.settingsState = { ...DEFAULT_SETTINGS };\n\n // Resolve layout persistence config. Treated as opt-in — defaults to\n // `false` so existing apps don't suddenly start writing to localStorage.\n if (options.persistLayouts) {\n const cfg = options.persistLayouts === true ? {} : options.persistLayouts;\n this.layoutKeyPrefix = cfg.keyPrefix ?? 'tcw:layout:';\n this.layoutDebounceMs = cfg.debounceMs ?? 1500;\n }\n\n // Resolve theme\n const isDark = this.resolveIsDark(options.theme);\n const resolvedTheme = this.resolveTheme(options.theme);\n\n // Initialize state\n this.state = {\n symbol: options.symbol ?? this.symbols[0] ?? 'BTCUSDT',\n timeframe: options.timeframe ?? '5m',\n chartType: options.chartOptions?.chartType ?? 'candlestick',\n isDark,\n activeIndicators: new Map(),\n activeTool: null,\n magnetEnabled: true,\n connectionState: 'connecting',\n connectionMessage: 'Connecting...',\n };\n\n\n // 1. Inject styles\n injectWidgetStyles();\n\n // 2. Create DOM skeleton\n this.root = document.createElement('div');\n this.root.className = 'tcw-root';\n this.root.dataset.tcwTheme = isDark ? 'dark' : 'light';\n container.appendChild(this.root);\n\n // 3. Create toolbar\n if (options.toolbar !== false) {\n this.toolbar = new WidgetToolbar(\n this.root,\n {\n symbols: this.symbols,\n timeframes: options.timeframes\n ? TIMEFRAMES.filter(tf => (options.timeframes as TimeFrame[]).includes(tf.value))\n : TIMEFRAMES,\n chartTypes: options.chartTypes\n ? CHART_TYPES.filter(ct => (options.chartTypes as ChartType[]).includes(ct.value))\n : CHART_TYPES,\n indicators: INDICATORS,\n popularIndicatorIds: POPULAR_INDICATORS,\n },\n {\n onSymbolClick: () => this.handleSymbolClick(),\n onTimeframe: (tf) => this.handleTimeframe(tf),\n onChartType: (type) => this.handleChartType(type),\n onAddIndicator: (id) => this.handleAddIndicator(id),\n onRemoveIndicator: (iid) => this.handleRemoveIndicator(iid),\n onScreenshot: () => this.chart.screenshot(),\n onSettings: () => this.openSettings(),\n onToggleTheme: () => this.handleToggleTheme(),\n onToggleReplay: () => this.toggleReplay(),\n onToggleAlerts: options.alerts !== false ? () => this.toggleAlerts() : undefined,\n onToggleObjects: options.objectTree !== false ? () => this.toggleObjects() : undefined,\n onBracket: options.trading !== false ? (side) => this.startBracket(side) : undefined,\n onToggleLadder: options.trading !== false && options.depthLadder ? () => this.depthLadder?.toggle() : undefined,\n },\n );\n }\n\n // 4. Create body\n const body = document.createElement('div');\n body.className = 'tcw-body';\n\n if (options.drawingTools !== false) {\n if (options.drawingFavorites) this.favoritesStore.seedDefaults(options.drawingFavorites);\n this.sidebar = new WidgetDrawingSidebar(\n body,\n { drawingToolGroups: DRAWING_TOOL_GROUPS, favorites: this.favoritesStore.list() as DrawingToolType[] },\n {\n onDrawingTool: (tool) => this.handleDrawingTool(tool),\n onCancelDrawing: () => this.handleCancelDrawing(),\n onToggleMagnet: () => this.handleToggleMagnet(),\n onToggleFavorite: (tool) => this.handleToggleFavorite(tool),\n onUndo: () => this.chart.undo(),\n onRedo: () => this.chart.redo(),\n onClearDrawings: () => {\n this.chart.clearDrawings();\n this.state = { ...this.state, activeTool: null };\n this.updateUI();\n },\n onToggleStyle: () => this.drawingStyle?.toggle(),\n },\n );\n }\n\n this.chartContainer = document.createElement('div');\n this.chartContainer.className = 'tcw-chart-container';\n body.appendChild(this.chartContainer);\n\n // Watchlist sidebar (right side). Appended AFTER the chart container so\n // it sits to the right of the canvas in the flexbox row.\n if (options.watchlist) {\n this.watchlist = new WidgetWatchlist(body, this.symbols, {\n onSelect: (sym) => { void this.setSymbol(sym); },\n });\n this.watchlist.setActive(this.state.symbol);\n }\n\n this.root.appendChild(body);\n\n // 5. Create chart\n this.chart = new Chart(this.chartContainer, {\n chartType: this.state.chartType,\n theme: resolvedTheme,\n autoScale: true,\n crosshair: { mode: 'magnet' },\n features: {\n drawings: true,\n drawingMagnet: true,\n drawingUndoRedo: true,\n indicators: true,\n trading: options.trading !== false,\n tradingContextMenu: options.trading !== false,\n volume: true,\n legend: true,\n crosshair: true,\n keyboard: true,\n screenshot: true,\n alerts: true,\n barCountdown: true,\n logScale: true,\n watermark: true,\n },\n ...options.chartOptions,\n });\n\n // Drag-and-drop CSV / JSON onto the chart container — instant data load.\n // Opt-out via `dragDropImport: false`. The adapter (live stream) keeps\n // running but the next bar update will append to whatever we just\n // loaded — that's the expected behavior when overlaying historical data.\n if (options.dragDropImport !== false) {\n this.dragDrop = new DragDropImporter(this.chartContainer, {\n onData: (data, result, file) => {\n this.setData(data);\n this.toast(`Loaded ${result.data.length} bars from ${file.name}` + (result.skipped > 0 ? ` (${result.skipped} skipped)` : ''));\n },\n onError: (err, file) => {\n this.toast(`${file.name}: ${err.message}`, 'error');\n },\n });\n this.dragDrop.attach();\n }\n\n // 6. Create status bar\n if (options.statusBar !== false) {\n this.statusBar = new WidgetStatusBar(this.root);\n }\n\n // 7. Create settings (lazy, not appended until opened)\n if (options.settings !== false) {\n this.settings = new WidgetSettings({\n onChange: (patch) => this.applySettings(patch),\n onReset: () => this.resetSettings(),\n onClose: () => {},\n });\n }\n\n // 8a. Symbol search\n this.symbolSearch = new WidgetSymbolSearch({\n onPick: (sym) => { void this.setSymbol(sym); },\n onClose: () => {},\n });\n this.hotkeySheet = new WidgetHotkeySheet({ onClose: () => {} });\n\n // Replay: click a revealed bar to jump the replay cursor there.\n this.chart.on('barClick', (e) => {\n if (!this.replayBar?.isMounted()) return;\n const idx = (e.payload as { barIndex?: number }).barIndex;\n if (typeof idx !== 'number') return;\n if (this.chart.getReplayState() === 'playing') this.chart.replayPause();\n this.chart.replaySeek(idx);\n this.replayBar.setState('paused');\n });\n\n // Data Window — precise OHLCV + indicator values at the hovered bar.\n this.dataWindow = new WidgetDataWindow(this.root, { formatPrice: (p) => this.formatAlertPrice(p) });\n this.chart.on('crosshairMove', (e) => {\n const p = e.payload as { barIndex?: number };\n this.lastHoverIndex = typeof p.barIndex === 'number' ? p.barIndex : null;\n if (this.dataWindow?.isOpen()) this.dataWindow.render(this.buildDataWindowModel());\n });\n\n // Drawing style + templates popover (paired with the sidebar palette button)\n if (options.drawingTools !== false) {\n this.drawingStyle = new WidgetDrawingStyle(\n this.root,\n {\n onStyleChange: (style) => {\n this.chart.setDrawingStyle(style);\n this.chart.setSelectedDrawingStyle(style);\n },\n getStyle: () => this.chart.getDrawingStyle(),\n },\n new DrawingTemplateStore(),\n );\n }\n\n // Bracket-order placement: floating confirm/cancel bar + event wiring.\n if (options.trading !== false) {\n this.bracketBar = new WidgetBracketBar(this.root, {\n onConfirm: () => this.chart.confirmBracket(),\n onCancel: () => {\n this.chart.cancelBracket();\n this.bracketBar?.hide();\n },\n });\n this.chart.on('bracketPlace', (e) => {\n const b = e.payload;\n this.bracketBar?.hide();\n this.toast(`${b.side === 'buy' ? 'Long' : 'Short'} bracket placed · ${b.riskReward.toFixed(2)}R`);\n });\n\n // Depth-of-market ladder (opt-in; fed via widget.setDepth)\n if (options.depthLadder) {\n this.depthLadder = new WidgetDepthLadder(this.root, {\n onTrade: (side, price) => {\n this.chart.placeOrderIntent({ side, type: 'limit', price });\n this.toast(`${side === 'buy' ? 'Buy' : 'Sell'} limit @ ${this.formatAlertPrice(price)}`);\n },\n formatPrice: (p) => this.formatAlertPrice(p),\n });\n }\n // Esc-cancel originates in the chart; reflect it in the bar.\n this.chart.on('dataUpdate', (e) => {\n const p = e.payload as { bracket?: string };\n if (p && p.bracket === 'cancelled') this.bracketBar?.hide();\n });\n }\n\n // 8a-bis. Price alerts panel (floating popover, toggled from the bell button)\n if (options.alerts !== false) {\n this.alertsPanel = new WidgetAlertsPanel(this.root, {\n onAdd: (price, condition, message, channel, label) => {\n this.chart.addAlert(price, condition, message, channel, label);\n },\n onRemove: (id) => this.chart.removeAlert(id),\n onClear: () => this.chart.clearAlerts(),\n getChannelValue: (channel) => this.getAlertChannelValue(channel),\n formatPrice: (p) => this.formatAlertPrice(p),\n });\n\n // Keep the panel list and toasts in sync with the chart's AlertManager.\n this.chart.on('alertAdd', () => this.refreshAlerts());\n this.chart.on('alertRemove', () => this.refreshAlerts());\n this.chart.on('alertUpdate', () => this.refreshAlerts());\n if (options.alertNotifications) {\n this.alertNotifier = new AlertNotifier(options.alertNotifications);\n }\n this.chart.on('alertTriggered', (e) => {\n const p = e.payload;\n const text = `Price ${this.formatAlertPrice(p.price)}${p.message ? ` — ${p.message}` : ''}`;\n this.toast(`🔔 Alert: ${text}`, 'info');\n this.alertNotifier?.notify(text);\n this.refreshAlerts();\n });\n }\n\n // 8a-ter. Object tree (indicators + drawings manager)\n if (options.objectTree !== false) {\n this.indicatorSettings = new WidgetIndicatorSettings(this.root, {\n onApply: (instanceId, params) => this.chart.updateIndicator(instanceId, params),\n onClose: () => {},\n });\n this.objectTree = new WidgetObjectTree(this.root, {\n onRemoveIndicator: (iid) => this.handleRemoveIndicator(iid),\n onConfigureIndicator: (iid) => this.openIndicatorSettings(iid),\n onToggleIndicatorVisible: (iid, visible) => {\n this.chart.setIndicatorVisible(iid, visible);\n this.refreshObjects();\n },\n onRemoveDrawing: (id) => {\n this.chart.removeDrawing(id);\n this.refreshObjects();\n },\n onToggleDrawingVisible: (id, visible) => {\n this.chart.setDrawingVisible(id, visible);\n this.refreshObjects();\n },\n onToggleDrawingLocked: (id, locked) => {\n this.chart.setDrawingLocked(id, locked);\n this.refreshObjects();\n },\n onAddCompare: () => this.handleAddCompare(),\n onRemoveCompare: (id) => this.handleRemoveCompare(id),\n });\n const refresh = () => { if (this.objectTree?.isOpen()) this.refreshObjects(); };\n this.chart.on('drawingCreate', refresh);\n this.chart.on('drawingRemove', refresh);\n this.chart.on('indicatorAdd', refresh);\n this.chart.on('indicatorRemove', refresh);\n }\n\n // 8b. Command palette\n this.commandPalette = new WidgetCommandPalette({\n onIndicator: (id) => this.handleAddIndicator(id),\n onChartType: (type) => this.handleChartType(type),\n onDrawingTool: (tool) => this.handleDrawingTool(tool),\n onTimeframe: (tf) => this.handleTimeframe(tf),\n onAction: (id) => this.handleAction(id),\n onClose: () => {},\n });\n\n this.boundGlobalKeydown = (e: KeyboardEvent) => {\n if ((e.ctrlKey || e.metaKey) && e.key === 'k') {\n e.preventDefault();\n this.toggleCommandPalette();\n } else if ((e.ctrlKey || e.metaKey) && (e.key === 'p' || e.key === 'P')) {\n // Ctrl/Cmd+P → symbol search (matches Bloomberg / many trading UIs)\n e.preventDefault();\n this.symbolSearch?.open(this.symbols, this.state.symbol);\n } else if (e.key === '?' && !e.ctrlKey && !e.metaKey && !e.altKey) {\n // Only fire when the user isn't typing into an input.\n const active = document.activeElement as HTMLElement | null;\n if (active && (active.tagName === 'INPUT' || active.tagName === 'TEXTAREA' || active.isContentEditable)) return;\n e.preventDefault();\n this.hotkeySheet?.open();\n }\n };\n document.addEventListener('keydown', this.boundGlobalKeydown);\n\n // 9. Connect stream\n if (options.adapter) {\n this.adapter = options.adapter;\n this.connectStream();\n }\n\n // Watchlist live-update loop. 1s cadence keeps DOM churn low while still\n // feeling responsive; for sub-second visual response, apps can call\n // `setWatchlistEntry` directly from their own WebSocket.\n if (this.watchlist) {\n this.watchlistInterval = setInterval(() => this.tickWatchlist(), 1000);\n }\n\n // Initial UI update\n this.updateUI();\n\n // 9. Fire onReady\n options.onReady?.(this.chart);\n\n // Deep-link restore: apply a `#tcw=` view from the URL when enabled.\n if (options.shareUrl && typeof location !== 'undefined') {\n const encoded = readShareHash(location.hash);\n if (encoded) void this.importState(encoded);\n }\n }\n\n // --- Public API ---\n\n /** Replace the searchable symbol catalog. Does not change the active symbol. */\n setSymbols(symbols: string[]): void {\n this.symbols = symbols;\n this.watchlist?.setSymbols(symbols);\n }\n\n async setSymbol(symbol: string): Promise<void> {\n // Flush the outgoing symbol's layout BEFORE switching state, so the\n // saved snapshot reflects what the user actually saw under that ticker.\n this.flushActiveLayout();\n this.state = { ...this.state, symbol };\n this.sessionRefPrice = null;\n this.options.onSymbolChange?.(symbol);\n this.updateUI();\n this.watchlist?.setActive(symbol);\n if (this.adapter) {\n await this.connectStream();\n }\n }\n\n /**\n * Push an entry into the watchlist (e.g., from your own WebSocket).\n * Call with the symbols you care about; the active symbol is updated\n * automatically from the chart's live data.\n */\n setWatchlistEntry(symbol: string, entry: Partial<WatchlistEntry>): void {\n this.watchlist?.setEntry(symbol, entry);\n }\n\n private tickWatchlist(): void {\n if (!this.watchlist) return;\n const data = this.chart.getData();\n if (data.length === 0) return;\n const last = data[data.length - 1];\n // Reference price: first bar of the loaded slice — that's the closest\n // approximation of \"session open\" without timezone bookkeeping. Apps\n // that need true session-open can override via `setWatchlistEntry`.\n if (this.sessionRefPrice === null) {\n this.sessionRefPrice = data[0].open;\n }\n\n const buf = this.watchlistSparkBuffer.get(this.state.symbol) ?? [];\n buf.push(last.close);\n if (buf.length > 40) buf.shift();\n this.watchlistSparkBuffer.set(this.state.symbol, buf);\n\n this.watchlist.setEntry(this.state.symbol, {\n lastPrice: last.close,\n refPrice: this.sessionRefPrice,\n sparkline: buf.slice(),\n });\n }\n\n async setTimeframe(tf: TimeFrame): Promise<void> {\n this.state = { ...this.state, timeframe: tf };\n this.options.onTimeframeChange?.(tf);\n this.updateUI();\n if (this.adapter) {\n await this.connectStream();\n return;\n }\n if (this.options.resampleTimeframes !== false) {\n this.applyTimeframeData();\n }\n }\n\n setTheme(theme: import('@tradecanvas/commons').ThemeName | Theme): void {\n const isDark = this.resolveIsDark(theme);\n const resolved = this.resolveTheme(theme);\n this.state = { ...this.state, isDark };\n this.root.dataset.tcwTheme = isDark ? 'dark' : 'light';\n this.chart.setTheme(resolved);\n this.updateUI();\n }\n\n getChart(): Chart {\n return this.chart;\n }\n\n destroy(): void {\n if (this.destroyed) return;\n this.destroyed = true;\n\n if (this.boundGlobalKeydown) {\n document.removeEventListener('keydown', this.boundGlobalKeydown);\n }\n this.flushActiveLayout();\n this.commandPalette?.destroy();\n this.symbolSearch?.destroy();\n this.hotkeySheet?.destroy();\n if (this.replayPollInterval) clearInterval(this.replayPollInterval);\n this.replayBar?.destroy();\n this.dragDrop?.detach();\n this.alertsPanel?.destroy();\n this.objectTree?.destroy();\n this.indicatorSettings?.destroy();\n this.drawingStyle?.destroy();\n this.bracketBar?.destroy();\n this.alertNotifier?.destroy();\n this.depthLadder?.destroy();\n this.dataWindow?.destroy();\n if (this.watchlistInterval) clearInterval(this.watchlistInterval);\n this.watchlist?.destroy();\n this.toolbar?.destroy();\n this.sidebar?.destroy();\n this.settings?.destroy();\n this.statusBar?.destroy();\n this.chart.destroy();\n this.root.remove();\n removeWidgetStyles();\n }\n\n // --- Internal handlers ---\n\n private handleSymbolClick(): void {\n // Opens the fuzzy search modal. The cycle-through behaviour the toolbar\n // used to do is gone — a real search scales past 3-4 symbols and matches\n // user expectations from TradingView, Bloomberg, etc.\n this.symbolSearch?.open(this.symbols, this.state.symbol);\n }\n\n private handleTimeframe(tf: TimeFrame): void {\n this.state = { ...this.state, timeframe: tf };\n this.options.onTimeframeChange?.(tf);\n this.updateUI();\n if (this.adapter) {\n // Live adapter owns the data — refetch at the native resolution.\n this.connectStream();\n return;\n }\n if (this.options.resampleTimeframes === false) return;\n // Static data: aggregate the base series locally. Lazily adopt whatever is\n // currently on the chart as the base if the host fed it via getChart().\n if (!this.baseSeries) {\n const current = this.chart.getData();\n if (current.length > 0) {\n this.baseSeries = current;\n this.baseTimeframeMs = inferTimeframeMs(current);\n }\n }\n this.applyTimeframeData();\n }\n\n /**\n * Load the widget's base series. Prefer this over `getChart().setData()` so\n * client-side timeframe resampling has a finest-resolution source to\n * aggregate from. The data is rendered at the current timeframe (resampled\n * when that timeframe is coarser than the data's native spacing).\n */\n setData(data: DataSeries): void {\n this.baseSeries = data;\n this.baseTimeframeMs = inferTimeframeMs(data);\n this.applyTimeframeData();\n }\n\n /** Render the base series at the active timeframe, resampling when coarser. */\n private applyTimeframeData(): void {\n if (!this.baseSeries) return;\n const targetMs = timeframeToMs(this.state.timeframe);\n if (this.baseTimeframeMs > 0 && targetMs > this.baseTimeframeMs) {\n const weekStartsOn = this.options.weekStartsOn ?? 1;\n this.chart.setData(resampleOHLCV(this.baseSeries, this.state.timeframe, { weekStartsOn }));\n } else {\n this.chart.setData(this.baseSeries);\n }\n }\n\n private toggleAlerts(): void {\n if (!this.alertsPanel) return;\n this.alertsPanel.toggle();\n if (this.alertsPanel.isOpen()) this.refreshAlerts();\n }\n\n private handleToggleFavorite(tool: DrawingToolType): void {\n const pinned = this.favoritesStore.toggle(tool);\n this.sidebar?.setFavorites(this.favoritesStore.list());\n this.toast(pinned ? 'Pinned to favorites' : 'Unpinned');\n }\n\n /** Encode the current view (symbol, timeframe, chart type, scale, indicators, drawings). */\n exportState(): string {\n const indicators = this.chart.getActiveIndicators().map((i) => ({\n id: i.id,\n params: i.params as Record<string, number | string | boolean>,\n }));\n return encodeWidgetState({\n v: 1,\n symbol: this.state.symbol,\n timeframe: this.state.timeframe,\n chartType: this.state.chartType,\n scaleMode: this.chart.getScaleMode(),\n indicators,\n drawings: this.chart.getDrawings(),\n });\n }\n\n /** Restore a view from an `exportState()` string. Returns false if malformed. */\n async importState(encoded: string): Promise<boolean> {\n const s = decodeWidgetState(encoded);\n if (!s) return false;\n\n // Symbol/timeframe first so any stream/layout restore happens before we\n // overlay the shared view on top.\n if (s.symbol && s.symbol !== this.state.symbol) await this.setSymbol(s.symbol);\n if (s.timeframe && s.timeframe !== this.state.timeframe) await this.setTimeframe(s.timeframe);\n\n if (s.chartType) this.handleChartType(s.chartType);\n this.chart.setScaleMode(s.scaleMode);\n\n for (const [, instanceId] of this.state.activeIndicators) this.chart.removeIndicator(instanceId);\n const map = new Map<string, string>();\n for (const ind of s.indicators) {\n const iid = this.chart.addIndicator(ind.id, ind.params);\n if (iid) map.set(ind.id, iid);\n }\n this.state = { ...this.state, activeIndicators: map };\n this.chart.setDrawings(s.drawings);\n this.updateUI();\n return true;\n }\n\n /** Copy the chart image to the clipboard, with a toast on success/failure. */\n async copyChartImage(): Promise<void> {\n const ok = await this.chart.copyScreenshot();\n this.toast(ok ? 'Chart image copied' : 'Copy failed — image clipboard unavailable', ok ? 'info' : 'error');\n }\n\n /** Copy a shareable deep-link (current view encoded in the URL hash) to the clipboard. */\n async copyShareLink(): Promise<void> {\n const base = typeof location !== 'undefined' ? location.href : '';\n const url = buildShareUrl(base, this.exportState());\n try {\n await navigator.clipboard.writeText(url);\n this.toast('Share link copied');\n } catch {\n this.toast('Copy failed — clipboard unavailable', 'error');\n }\n }\n\n /** Feed order-book depth to the chart overlay, depth ladder, and heatmap. */\n setDepth(depth: DepthData | null): void {\n this.chart.setDepthData(depth);\n this.depthLadder?.setData(depth);\n if (depth) this.chart.pushDepthSnapshot(depth);\n }\n\n /** Begin a draggable bracket order at the latest price and show the action bar. */\n startBracket(side: 'buy' | 'sell'): void {\n if (this.chart.startBracket(side)) {\n this.bracketBar?.show(side);\n }\n }\n\n private buildDataWindowModel(): DataWindowModel {\n const data = this.chart.getData();\n const idx = this.lastHoverIndex;\n if (idx === null || idx < 0 || idx >= data.length) {\n return { ohlc: null, change: 0, changePct: 0, indicators: [] };\n }\n const bar = data[idx];\n const prevClose = idx > 0 ? data[idx - 1].close : bar.open;\n const change = bar.close - prevClose;\n const changePct = prevClose !== 0 ? (change / prevClose) * 100 : 0;\n\n const indicators = this.chart.getActiveIndicators().map((ind) => {\n const series = this.chart.getIndicatorOutput(ind.instanceId)?.series;\n const point = series?.[idx] ?? null;\n const values = point\n ? Object.entries(point)\n .filter(([, v]) => typeof v === 'number' && Number.isFinite(v))\n .map(([key, v]) => ({ key, value: v as number }))\n : [];\n return { name: ind.descriptor.name, values };\n }).filter((i) => i.values.length > 0);\n\n return {\n ohlc: { open: bar.open, high: bar.high, low: bar.low, close: bar.close, volume: bar.volume },\n change,\n changePct,\n indicators,\n };\n }\n\n private toggleDataWindow(): void {\n if (!this.dataWindow) return;\n this.dataWindow.toggle();\n if (this.dataWindow.isOpen()) this.dataWindow.render(this.buildDataWindowModel());\n }\n\n private toggleObjects(): void {\n if (!this.objectTree) return;\n this.objectTree.toggle();\n if (this.objectTree.isOpen()) this.refreshObjects();\n }\n\n private openIndicatorSettings(instanceId: string): void {\n if (!this.indicatorSettings) return;\n const ind = this.chart.getActiveIndicators().find((i) => i.instanceId === instanceId);\n if (!ind) return;\n this.indicatorSettings.open({\n instanceId,\n name: ind.descriptor.name,\n defaults: ind.descriptor.defaultConfig,\n params: ind.params,\n });\n }\n\n private refreshObjects(): void {\n if (!this.objectTree) return;\n const indicators = this.chart.getActiveIndicators().map((i) => ({\n instanceId: i.instanceId,\n name: i.descriptor.name,\n visible: i.visible,\n }));\n const drawings = this.chart.getDrawings().map((d) => ({\n id: d.id,\n label: drawingTypeLabel(d.type),\n visible: d.visible,\n locked: d.locked,\n }));\n const compares = this.compares.map((c) => ({ id: c.id, label: c.symbol, color: c.color }));\n this.objectTree.setObjects(indicators, drawings, compares);\n }\n\n private async handleAddCompare(): Promise<void> {\n if (!this.adapter) {\n this.toast('Comparison needs a live data adapter', 'error');\n return;\n }\n const taken = new Set([this.state.symbol, ...this.compares.map((c) => c.symbol)]);\n const options = this.symbols.filter((s) => !taken.has(s));\n this.symbolSearch?.open(options.length ? options : this.symbols, this.state.symbol, (symbol) => {\n void this.addCompareSymbol(symbol);\n });\n }\n\n /** Overlay another symbol's normalized series. Fetches history via the adapter. */\n async addCompareSymbol(symbol: string): Promise<void> {\n if (!this.adapter || this.compares.some((c) => c.symbol === symbol)) return;\n const color = COMPARE_COLORS[this.compares.length % COMPARE_COLORS.length];\n const id = `cmp_${symbol}`;\n try {\n const bars = await this.adapter.fetchHistory(symbol, this.state.timeframe, this.options.historyLimit ?? 500);\n // Percent mode normalizes mixed-price symbols (e.g. BTC vs a $2 alt) onto\n // a shared % axis — the right default for comparison.\n if (this.compares.length === 0) this.chart.setCompareMode('percent');\n this.chart.addCompareSymbol(id, symbol, bars, color);\n this.compares = [...this.compares, { id, symbol, color }];\n this.refreshObjects();\n this.toast(`Comparing ${symbol}`);\n } catch (err: unknown) {\n this.toast(`${symbol}: ${err instanceof Error ? err.message : 'failed to load'}`, 'error');\n }\n }\n\n private handleRemoveCompare(id: string): void {\n this.chart.removeCompareSymbol(id);\n this.compares = this.compares.filter((c) => c.id !== id);\n this.refreshObjects();\n }\n\n /** Refetch every comparison overlay at the current symbol/timeframe. */\n private async refetchCompares(): Promise<void> {\n if (!this.adapter || this.compares.length === 0) return;\n // A comparison against the now-active symbol is redundant — drop it.\n const stale = this.compares.filter((c) => c.symbol === this.state.symbol);\n for (const c of stale) this.handleRemoveCompare(c.id);\n\n for (const c of this.compares) {\n try {\n const bars = await this.adapter.fetchHistory(c.symbol, this.state.timeframe, this.options.historyLimit ?? 500);\n this.chart.updateCompareData(c.id, bars);\n } catch { /* leave the stale overlay in place if the refetch fails */ }\n }\n }\n\n private refreshAlerts(): void {\n if (!this.alertsPanel) return;\n this.alertsPanel.setSources(this.buildAlertSources());\n this.alertsPanel.setAlerts(\n this.chart.getAlerts().map((a) => ({\n id: a.id,\n price: a.price,\n condition: a.condition,\n message: a.message,\n triggered: a.triggered,\n channel: a.channel,\n label: a.label,\n })),\n );\n }\n\n /** Price + every active indicator line, as selectable alert sources. */\n private buildAlertSources(): { channel: string; label: string }[] {\n const sources = [{ channel: 'price', label: 'Price' }];\n for (const ind of this.chart.getActiveIndicators()) {\n // Use the latest point — multi-output indicators (MACD, Stochastic) only\n // have all their lines populated once warmed up; the first point may not.\n const series = this.chart.getIndicatorOutput(ind.instanceId)?.series;\n const point = series && series.length > 0 ? series[series.length - 1] : null;\n const keys = point ? Object.keys(point).filter((k) => typeof point[k] === 'number') : [];\n for (const key of keys) {\n const label = keys.length > 1 ? `${ind.descriptor.name} ${key}` : ind.descriptor.name;\n sources.push({ channel: `${ind.instanceId}:${key}`, label });\n }\n }\n return sources;\n }\n\n /** Latest value for an alert source channel (price or indicator line). */\n private getAlertChannelValue(channel: string): number | null {\n const data = this.chart.getData();\n if (channel === 'price') return data.length > 0 ? data[data.length - 1].close : null;\n const sep = channel.indexOf(':');\n if (sep < 0 || data.length === 0) return null;\n const instanceId = channel.slice(0, sep);\n const key = channel.slice(sep + 1);\n const v = this.chart.getIndicatorOutput(instanceId)?.series?.[data.length - 1]?.[key];\n return typeof v === 'number' && Number.isFinite(v) ? v : null;\n }\n\n private formatAlertPrice(price: number): string {\n // No fixed precision config on the widget — pick digits from magnitude so\n // BTC (64,200.5) and a sub-dollar alt (0.04821) both read sensibly.\n const abs = Math.abs(price);\n const digits = abs >= 1000 ? 2 : abs >= 1 ? 4 : 6;\n const locale = this.settingsState.numberLocale || undefined;\n return price.toLocaleString(locale, { minimumFractionDigits: 2, maximumFractionDigits: digits });\n }\n\n private handleChartType(type: ChartType): void {\n this.state = { ...this.state, chartType: type };\n this.chart.setChartType(type);\n this.updateUI();\n }\n\n private handleAddIndicator(indId: string): void {\n if (this.state.activeIndicators.has(indId)) {\n // Toggle off\n const instanceId = this.state.activeIndicators.get(indId)!;\n this.chart.removeIndicator(instanceId);\n const next = new Map(this.state.activeIndicators);\n next.delete(indId);\n this.state = { ...this.state, activeIndicators: next };\n } else {\n const instanceId = this.chart.addIndicator(indId);\n if (instanceId) {\n const next = new Map(this.state.activeIndicators);\n next.set(indId, instanceId);\n this.state = { ...this.state, activeIndicators: next };\n }\n }\n this.updateUI();\n }\n\n private handleRemoveIndicator(instanceId: string): void {\n this.chart.removeIndicator(instanceId);\n const next = new Map(this.state.activeIndicators);\n for (const [id, iid] of next.entries()) {\n if (iid === instanceId) {\n next.delete(id);\n break;\n }\n }\n this.state = { ...this.state, activeIndicators: next };\n this.updateUI();\n }\n\n private toggleCommandPalette(): void {\n if (this.commandPalette?.isOpen()) {\n this.commandPalette.close();\n return;\n }\n this.commandPalette?.open(this.buildCommandItems());\n }\n\n private buildCommandItems(): CommandItem[] {\n const items: CommandItem[] = [];\n\n for (const ind of INDICATORS) {\n items.push({\n id: ind.id,\n label: ind.name,\n category: 'indicator',\n active: this.state.activeIndicators.has(ind.id),\n });\n }\n\n for (const ct of CHART_TYPES) {\n items.push({\n id: ct.value,\n label: ct.label,\n category: 'chartType',\n active: this.state.chartType === ct.value,\n });\n }\n\n for (const group of DRAWING_TOOL_GROUPS) {\n for (const tool of group.tools) {\n items.push({\n id: tool.value,\n label: tool.label,\n category: 'drawing',\n active: this.state.activeTool === tool.value,\n });\n }\n }\n\n for (const tf of TIMEFRAMES) {\n items.push({\n id: tf.value,\n label: tf.label,\n category: 'timeframe',\n active: this.state.timeframe === tf.value,\n });\n }\n\n items.push(\n { id: 'screenshot', label: 'Screenshot', category: 'action', shortcut: '' },\n { id: 'copyImage', label: 'Copy Chart Image', category: 'action' },\n { id: 'toggleTheme', label: 'Toggle Theme', category: 'action' },\n { id: 'settings', label: 'Settings', category: 'action' },\n { id: 'shareView', label: 'Share View (copy link)', category: 'action' },\n { id: 'autoFib', label: 'Auto Fibonacci (visible swing)', category: 'action' },\n { id: 'dataWindow', label: 'Toggle Data Window', category: 'action' },\n { id: 'clearDrawings', label: 'Clear All Drawings', category: 'action' },\n );\n\n return items;\n }\n\n private handleAction(id: string): void {\n switch (id) {\n case 'screenshot':\n this.chart.screenshot();\n break;\n case 'toggleTheme':\n this.handleToggleTheme();\n break;\n case 'settings':\n this.openSettings();\n break;\n case 'copyImage':\n void this.copyChartImage();\n break;\n case 'shareView':\n void this.copyShareLink();\n break;\n case 'autoFib': {\n const id = this.chart.autoFib();\n this.toast(id ? 'Auto Fibonacci added' : 'No clear swing in view');\n break;\n }\n case 'dataWindow':\n this.toggleDataWindow();\n break;\n case 'clearDrawings':\n this.chart.clearDrawings();\n this.state = { ...this.state, activeTool: null };\n this.updateUI();\n break;\n }\n }\n\n private handleDrawingTool(tool: DrawingToolType): void {\n this.state = { ...this.state, activeTool: tool };\n this.chart.setDrawingTool(tool);\n this.updateUI();\n }\n\n private handleCancelDrawing(): void {\n this.state = { ...this.state, activeTool: null };\n this.chart.setDrawingTool(null);\n this.updateUI();\n }\n\n private handleToggleMagnet(): void {\n const magnetEnabled = !this.state.magnetEnabled;\n this.state = { ...this.state, magnetEnabled };\n this.chart.setDrawingMagnet(magnetEnabled);\n this.updateUI();\n }\n\n private handleToggleTheme(): void {\n const isDark = !this.state.isDark;\n this.state = { ...this.state, isDark };\n this.root.dataset.tcwTheme = isDark ? 'dark' : 'light';\n this.chart.setTheme(isDark ? DARK_THEME : LIGHT_THEME);\n this.chart.setWatermark(this.state.symbol.replace('USDT', ' / USDT'), {\n fontSize: 48,\n color: isDark ? 'rgba(255,255,255,0.03)' : 'rgba(0,0,0,0.03)',\n });\n this.updateUI();\n }\n\n private openSettings(): void {\n this.settings?.open(this.settingsState);\n }\n\n // --- Toast ---\n\n /**\n * Show a transient toast inside the widget. Auto-dismisses after 3.5s.\n * Used by the drag-drop importer for success / failure feedback, but\n * exposed so apps can post their own (e.g. \"alert triggered at 64,200\").\n */\n toast(message: string, kind: 'info' | 'error' = 'info'): void {\n const el = document.createElement('div');\n el.className = `tcw-toast ${kind === 'error' ? 'tcw-toast-error' : ''}`;\n el.textContent = message;\n this.root.appendChild(el);\n // Trigger CSS transition on next frame\n requestAnimationFrame(() => el.classList.add('tcw-toast-in'));\n setTimeout(() => {\n el.classList.remove('tcw-toast-in');\n el.addEventListener('transitionend', () => el.remove(), { once: true });\n // Hard timeout in case transitionend doesn't fire (display:none, etc.)\n setTimeout(() => el.remove(), 400);\n }, 3500);\n }\n\n // --- Layout persistence ---\n\n /**\n * Wipe the layout saved for `symbol` (or the active symbol if omitted).\n * Useful as an \"Reset layout\" command in user-facing menus.\n */\n clearSavedLayout(symbol?: string): void {\n if (!this.layoutKeyPrefix) return;\n const target = symbol ?? this.state.symbol;\n try {\n localStorage.removeItem(this.layoutKeyPrefix + target);\n } catch { /* localStorage may be unavailable (private mode, SSR, etc.) */ }\n }\n\n private applySymbolLayout(symbol: string): void {\n if (!this.layoutKeyPrefix) return;\n const key = this.layoutKeyPrefix + symbol;\n this.activeLayoutKey = key;\n\n try {\n // Best-effort load. If parsing or any restore step throws, we silently\n // fall back to a fresh layout — a corrupted layout shouldn't break the\n // chart.\n const ok = this.chart.loadStateFromStorage(key);\n if (ok) this.rebuildActiveIndicatorsMapFromChart();\n } catch { /* swallow — layout will be rebuilt from user actions */ }\n\n // Wire chart-level auto-save so any further drawing/indicator change\n // flushes itself into this symbol's slot.\n this.chart.setAutoSave(key, this.layoutDebounceMs);\n }\n\n private flushActiveLayout(): void {\n if (!this.activeLayoutKey) return;\n try { this.chart.saveState(this.activeLayoutKey); } catch { /* same */ }\n this.chart.disableAutoSave();\n this.activeLayoutKey = null;\n }\n\n /**\n * After loading a layout, the chart restores indicator instances but our\n * `state.activeIndicators` map (used to render the chip strip) is stale.\n * Rebuild it from the live `getActiveIndicators` list.\n */\n private rebuildActiveIndicatorsMapFromChart(): void {\n const next = new Map<string, string>();\n for (const a of this.chart.getActiveIndicators()) {\n next.set(a.id, a.instanceId);\n }\n this.state = { ...this.state, activeIndicators: next };\n this.updateUI();\n }\n\n // --- Replay ---\n\n private toggleReplay(): void {\n if (this.replayBar?.isMounted()) {\n this.exitReplay();\n } else {\n this.enterReplay();\n }\n }\n\n private enterReplay(): void {\n const data = this.chart.getData();\n if (data.length < 2) return;\n\n // Snapshot full series so we can restore it on exit. The chart's\n // dataManager gets mutated to slices during replay.\n this.replayOriginalData = data.slice();\n\n // Mount the scrubber bar inside the chart container so it floats above the\n // canvas. It owns its own absolute positioning via the .tcw-replay-bar CSS.\n this.replayBar = new WidgetReplayBar({\n onPlay: () => {\n if (this.chart.getReplayState() === 'paused') {\n this.chart.replayResume();\n } else {\n this.chart.replayStart({ speed: this.replaySpeed, interval: 200 });\n }\n this.replayBar?.setState('playing');\n },\n onPause: () => {\n this.chart.replayPause();\n this.replayBar?.setState('paused');\n },\n onStop: () => {\n this.chart.replayStop();\n this.replayBar?.setState('paused');\n },\n onStepBack: () => {\n const p = this.chart.getReplayProgress();\n if (this.chart.getReplayState() === 'playing') this.chart.replayPause();\n this.chart.replaySeek(Math.max(0, p.current - 1));\n this.replayBar?.setState('paused');\n },\n onStepForward: () => {\n const p = this.chart.getReplayProgress();\n if (this.chart.getReplayState() === 'playing') this.chart.replayPause();\n this.chart.replaySeek(Math.min(p.total - 1, p.current + 1));\n this.replayBar?.setState('paused');\n },\n onSeek: (idx) => {\n if (this.chart.getReplayState() === 'playing') this.chart.replayPause();\n this.chart.replaySeek(idx);\n this.replayBar?.setState('paused');\n },\n onSpeedChange: (s) => {\n this.replaySpeed = s;\n this.chart.setReplaySpeed(s);\n },\n onClose: () => this.exitReplay(),\n });\n this.replayBar.mount(this.chartContainer, { total: data.length, speed: this.replaySpeed });\n\n // Boot replay paused at bar 1 so the user sees a starting state. Then\n // start polling progress for the scrubber — cheap, runs at 200ms.\n this.chart.replayStart({ speed: this.replaySpeed, interval: 200, startIndex: 1 });\n this.chart.replayPause();\n this.replayBar.setState('paused');\n\n this.replayPollInterval = setInterval(() => {\n if (!this.replayBar?.isMounted()) return;\n const p = this.chart.getReplayProgress();\n this.replayBar.setProgress(p.current, p.total);\n const state = this.chart.getReplayState();\n if (state === 'stopped') {\n this.replayBar.setState('paused');\n } else {\n this.replayBar.setState(state);\n }\n }, 150);\n }\n\n private exitReplay(): void {\n if (this.replayPollInterval) {\n clearInterval(this.replayPollInterval);\n this.replayPollInterval = null;\n }\n this.chart.replayStop();\n this.replayBar?.unmount();\n this.replayBar = null;\n if (this.replayOriginalData) {\n this.chart.setData(this.replayOriginalData);\n this.replayOriginalData = null;\n }\n }\n\n private applySettings(patch: Partial<ChartSettingsState>): void {\n this.settingsState = { ...this.settingsState, ...patch };\n\n if (patch.gridVisible !== undefined) this.chart.setGridVisible(patch.gridVisible);\n if (patch.volumeVisible !== undefined) this.chart.setVolumeVisible(patch.volumeVisible);\n if (patch.volumeProfileVisible !== undefined) this.chart.setVolumeProfileVisible(patch.volumeProfileVisible);\n if (patch.marketProfileVisible !== undefined) this.chart.setMarketProfileVisible(patch.marketProfileVisible);\n if (patch.marketProfileSplit !== undefined) this.chart.setMarketProfileConfig({ splitBySession: patch.marketProfileSplit });\n if (patch.marketProfileLetters !== undefined) this.chart.setMarketProfileConfig({ letters: patch.marketProfileLetters });\n if (patch.marketProfileBuckets !== undefined) this.chart.setMarketProfileConfig({ buckets: patch.marketProfileBuckets });\n if (patch.marketProfileOpacity !== undefined) this.chart.setMarketProfileConfig({ opacity: patch.marketProfileOpacity });\n if (patch.depthHeatmapVisible !== undefined) this.chart.setDepthHeatmapVisible(patch.depthHeatmapVisible);\n if (patch.depthHeatmapOpacity !== undefined) this.chart.setDepthHeatmapConfig({ opacity: patch.depthHeatmapOpacity });\n if (patch.sessionShadingVisible !== undefined) this.chart.setSessionShadingVisible(patch.sessionShadingVisible);\n if (patch.pivotMarkersVisible !== undefined) this.chart.setPivotMarkersVisible(patch.pivotMarkersVisible);\n if (patch.pivotStrength !== undefined) this.chart.setPivotMarkersConfig({ left: patch.pivotStrength, right: patch.pivotStrength });\n if (patch.pivotStructureLabels !== undefined) this.chart.setPivotMarkersConfig({ structureLabels: patch.pivotStructureLabels });\n if (patch.periodLevelsVisible !== undefined) this.chart.setPeriodLevelsVisible(patch.periodLevelsVisible);\n if (patch.periodLevelsPeriod !== undefined) this.chart.setPeriodLevelsPeriod(patch.periodLevelsPeriod);\n if (patch.crosshairMode !== undefined) this.chart.setCrosshairMode(patch.crosshairMode);\n if (patch.autoScale !== undefined) this.chart.setAutoScale(patch.autoScale);\n if (patch.scaleMode !== undefined) {\n this.chart.setScaleMode(patch.scaleMode);\n // Keep the legacy logScale flag mirrored so persisted layouts stay valid.\n this.settingsState = { ...this.settingsState, logScale: patch.scaleMode === 'logarithmic' };\n } else if (patch.logScale !== undefined) {\n this.chart.setLogScale(patch.logScale);\n this.settingsState = { ...this.settingsState, scaleMode: patch.logScale ? 'logarithmic' : 'regular' };\n }\n if (patch.numberLocale !== undefined) this.chart.setNumberLocale(patch.numberLocale);\n if (patch.timezone !== undefined) {\n this.chart.setTimezoneOffset(patch.timezone === 'local' ? null : Number(patch.timezone));\n }\n\n // Apply theme colors\n const currentTheme = this.chart.getTheme();\n const themeUpdate = { ...currentTheme } as Record<string, unknown>;\n let themeChanged = false;\n\n if (patch.candleUpColor !== undefined) { themeUpdate.candleUp = patch.candleUpColor; themeChanged = true; }\n if (patch.candleDownColor !== undefined) { themeUpdate.candleDown = patch.candleDownColor; themeChanged = true; }\n if (patch.candleUpWick !== undefined) { themeUpdate.candleUpWick = patch.candleUpWick; themeChanged = true; }\n if (patch.candleDownWick !== undefined) { themeUpdate.candleDownWick = patch.candleDownWick; themeChanged = true; }\n if (patch.backgroundColor !== undefined) { themeUpdate.background = patch.backgroundColor; themeChanged = true; }\n if (patch.gridColor !== undefined) { themeUpdate.grid = patch.gridColor; themeChanged = true; }\n\n if (themeChanged) {\n this.chart.setTheme(themeUpdate as unknown as Theme);\n }\n }\n\n private resetSettings(): void {\n this.settingsState = { ...DEFAULT_SETTINGS };\n this.applySettings(this.settingsState);\n }\n\n private async connectStream(): Promise<void> {\n if (!this.adapter) return;\n\n this.state = {\n ...this.state,\n connectionState: 'connecting',\n connectionMessage: 'Connecting...',\n };\n this.updateUI();\n\n try {\n this.chart.disconnectStream();\n await this.chart.connect({\n adapter: this.adapter,\n symbol: this.state.symbol,\n timeframe: this.state.timeframe,\n historyLimit: this.options.historyLimit ?? 500,\n });\n\n this.chart.setWatermark(this.state.symbol.replace('USDT', ' / USDT'), {\n fontSize: 48,\n color: this.state.isDark ? 'rgba(255,255,255,0.03)' : 'rgba(0,0,0,0.03)',\n });\n\n // Re-apply per-symbol layout (indicators, drawings, chart type) after\n // the new history is in. Doing this *after* connect ensures indicators\n // recalculate against the loaded data, not the previous symbol's data.\n this.applySymbolLayout(this.state.symbol);\n\n this.state = {\n ...this.state,\n connectionState: 'connected',\n connectionMessage: 'Live',\n };\n\n // Re-pull comparison overlays at the (possibly new) timeframe so they\n // stay aligned with the main series. Drop the active symbol if it ended\n // up in the compare set after a symbol switch.\n void this.refetchCompares();\n } catch (err: unknown) {\n this.state = {\n ...this.state,\n connectionState: 'error',\n connectionMessage: err instanceof Error ? err.message : 'Connection failed',\n };\n }\n\n this.updateUI();\n }\n\n private updateUI(): void {\n this.toolbar?.update(this.state);\n this.sidebar?.update(this.state);\n this.statusBar?.update({\n connectionState: this.state.connectionState,\n message: this.state.connectionMessage,\n symbol: this.state.symbol,\n timeframe: this.state.timeframe,\n });\n }\n\n private resolveIsDark(theme?: import('@tradecanvas/commons').ThemeName | Theme): boolean {\n if (theme === undefined || theme === 'dark') return true;\n if (theme === 'light') return false;\n // If it's a Theme object, check background color\n if (typeof theme === 'object' && theme.background) {\n return this.isColorDark(theme.background);\n }\n return true;\n }\n\n private resolveTheme(theme?: import('@tradecanvas/commons').ThemeName | Theme): Theme {\n if (theme === undefined || theme === 'dark') return DARK_THEME;\n if (theme === 'light') return LIGHT_THEME;\n if (typeof theme === 'object') return theme as Theme;\n return DARK_THEME;\n }\n\n private isColorDark(color: string): boolean {\n // Simple heuristic: if it starts with # and R+G+B < 384 (half of 768)\n if (color.startsWith('#') && color.length >= 7) {\n const r = parseInt(color.slice(1, 3), 16);\n const g = parseInt(color.slice(3, 5), 16);\n const b = parseInt(color.slice(5, 7), 16);\n return (r + g + b) < 384;\n }\n return true;\n }\n}\n"],"mappings":"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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":[],"sources":["../../src/io/resampleOHLCV.ts","../../src/widget/widgetConfig.ts","../../src/widget/WidgetStyles.ts","../../src/widget/icons.ts","../../src/widget/WidgetDropdown.ts","../../src/widget/WidgetToolbar.ts","../../src/widget/WidgetDrawingSidebar.ts","../../src/widget/WidgetSettings.ts","../../src/widget/WidgetStatusBar.ts","../../src/widget/WidgetCommandPalette.ts","../../src/widget/WidgetSymbolSearch.ts","../../src/widget/WidgetHotkeySheet.ts","../../src/widget/WidgetReplayBar.ts","../../src/widget/WidgetWatchlist.ts","../../src/widget/WidgetAlertsPanel.ts","../../src/widget/WidgetObjectTree.ts","../../src/widget/WidgetIndicatorSettings.ts","../../src/widget/DrawingTemplateStore.ts","../../src/widget/WidgetDrawingStyle.ts","../../src/widget/DrawingFavoritesStore.ts","../../src/widget/WidgetBracketBar.ts","../../src/widget/AlertNotifier.ts","../../src/widget/ladderRows.ts","../../src/widget/WidgetDepthLadder.ts","../../src/widget/WidgetDataWindow.ts","../../src/widget/widgetShareState.ts","../../src/widget/ChartWidget.ts"],"sourcesContent":["import type { DataSeries, OHLCBar, TimeFrame } from '@tradecanvas/commons';\nimport { timeframeToMs, timeframeBucketStart } from '@tradecanvas/commons';\n\nexport interface ResampleOptions {\n /** 0 = Sunday, 1 = Monday (default) — anchor for weekly buckets. */\n weekStartsOn?: 0 | 1;\n}\n\n/**\n * Aggregate a finer OHLCV series into a coarser timeframe.\n *\n * Bars are grouped by calendar-aware bucket (see `timeframeBucketStart`):\n * open = first bar's open, high/low = extremes, close = last bar's close,\n * volume = sum. Input bars are assumed sorted ascending by `time` and are\n * never mutated.\n *\n * Upsampling (target finer than source) cannot synthesize data — pass a target\n * coarser than the source. Use `inferTimeframeMs` to detect the source spacing.\n */\nexport function resampleOHLCV(\n bars: DataSeries,\n target: TimeFrame,\n opts: ResampleOptions = {},\n): DataSeries {\n if (bars.length === 0) return [];\n const weekStartsOn = opts.weekStartsOn ?? 1;\n\n const out: OHLCBar[] = [];\n let current: OHLCBar | null = null;\n let currentKey = Number.NaN;\n\n for (const bar of bars) {\n const key = timeframeBucketStart(bar.time, target, weekStartsOn);\n if (current === null || key !== currentKey) {\n if (current !== null) out.push(current);\n current = {\n time: key,\n open: bar.open,\n high: bar.high,\n low: bar.low,\n close: bar.close,\n volume: bar.volume,\n };\n currentKey = key;\n } else {\n current = {\n time: current.time,\n open: current.open,\n high: Math.max(current.high, bar.high),\n low: Math.min(current.low, bar.low),\n close: bar.close,\n volume: current.volume + bar.volume,\n };\n }\n }\n if (current !== null) out.push(current);\n return out;\n}\n\n/**\n * Estimate the source bar spacing in milliseconds from the median gap between\n * consecutive bars. Robust to occasional gaps (weekends, halts). Returns 0 for\n * series with fewer than two bars.\n */\nexport function inferTimeframeMs(bars: DataSeries): number {\n if (bars.length < 2) return 0;\n const gaps: number[] = [];\n for (let i = 1; i < bars.length; i++) {\n const gap = bars[i].time - bars[i - 1].time;\n if (gap > 0) gaps.push(gap);\n }\n if (gaps.length === 0) return 0;\n gaps.sort((a, b) => a - b);\n return gaps[Math.floor(gaps.length / 2)];\n}\n\n/**\n * Whether `target` is coarser than (or equal to) the source spacing, i.e. a\n * valid downsample. A non-positive `sourceMs` (unknown) is treated as valid.\n */\nexport function canResample(sourceMs: number, target: TimeFrame): boolean {\n if (sourceMs <= 0) return true;\n return timeframeToMs(target) >= sourceMs;\n}\n","import type { ChartType, DrawingToolType, TimeFrame } from '@tradecanvas/commons';\nimport type { IndicatorDef, DrawingToolGroupDef, ChartSettingsState } from './types.js';\n\nexport const TIMEFRAMES: { label: string; value: TimeFrame }[] = [\n { label: '1m', value: '1m' },\n { label: '5m', value: '5m' },\n { label: '15m', value: '15m' },\n { label: '1H', value: '1h' },\n { label: '4H', value: '4h' },\n { label: '1D', value: '1d' },\n];\n\nexport const CHART_TYPES: { label: string; value: ChartType }[] = [\n { label: 'Candlestick', value: 'candlestick' },\n { label: 'Line', value: 'line' },\n { label: 'Area', value: 'area' },\n { label: 'Bar', value: 'bar' },\n { label: 'Heikin-Ashi', value: 'heikinAshi' },\n { label: 'Hollow Candle', value: 'hollowCandle' },\n { label: 'Baseline', value: 'baseline' },\n { label: 'Volume Candles', value: 'volumeCandles' },\n { label: 'Equivolume', value: 'equivolume' },\n { label: 'HLC Area', value: 'hlcArea' },\n { label: 'Step Line', value: 'stepLine' },\n { label: 'Line + Markers', value: 'lineWithMarkers' },\n];\n\nexport const DRAWING_TOOL_GROUPS: DrawingToolGroupDef[] = [\n {\n label: 'Lines',\n tools: [\n { label: 'Trend Line', value: 'trendLine' as DrawingToolType },\n { label: 'Ray', value: 'ray' as DrawingToolType },\n { label: 'Extended Line', value: 'extendedLine' as DrawingToolType },\n ],\n },\n {\n label: 'Horizontal/Vertical',\n tools: [\n { label: 'Horizontal Line', value: 'horizontalLine' as DrawingToolType },\n { label: 'Vertical Line', value: 'verticalLine' as DrawingToolType },\n ],\n },\n {\n label: 'Channels',\n tools: [\n { label: 'Parallel Channel', value: 'parallelChannel' as DrawingToolType },\n { label: 'Regression Channel', value: 'regressionChannel' as DrawingToolType },\n ],\n },\n {\n label: 'Fibonacci',\n tools: [\n { label: 'Fib Retracement', value: 'fibRetracement' as DrawingToolType },\n { label: 'Fib Extension', value: 'fibExtension' as DrawingToolType },\n ],\n },\n {\n label: 'Shapes',\n tools: [\n { label: 'Rectangle', value: 'rectangle' as DrawingToolType },\n { label: 'Ellipse', value: 'ellipse' as DrawingToolType },\n { label: 'Triangle', value: 'triangle' as DrawingToolType },\n ],\n },\n {\n label: 'Gann & Advanced',\n tools: [\n { label: 'Pitchfork', value: 'pitchfork' as DrawingToolType },\n { label: 'Gann Fan', value: 'gannFan' as DrawingToolType },\n { label: 'Gann Box', value: 'gannBox' as DrawingToolType },\n { label: 'Elliott Wave', value: 'elliottWave' as DrawingToolType },\n ],\n },\n {\n label: 'Measure',\n tools: [\n { label: 'Price Range', value: 'priceRange' as DrawingToolType },\n { label: 'Date Range', value: 'dateRange' as DrawingToolType },\n { label: 'Measure', value: 'measure' as DrawingToolType },\n ],\n },\n {\n label: 'Annotation',\n tools: [\n { label: 'Text', value: 'text' as DrawingToolType },\n { label: 'Arrow', value: 'arrow' as DrawingToolType },\n ],\n },\n];\n\nexport const INDICATORS: IndicatorDef[] = [\n { id: 'sma', name: 'SMA', type: 'overlay' },\n { id: 'ema', name: 'EMA', type: 'overlay' },\n { id: 'hma', name: 'Hull MA', type: 'overlay' },\n { id: 'mtfma', name: 'MTF Moving Average', type: 'overlay' },\n { id: 'bb', name: 'Bollinger Bands', type: 'overlay' },\n { id: 'vwap', name: 'VWAP', type: 'overlay' },\n { id: 'avwap', name: 'Anchored VWAP', type: 'overlay' },\n { id: 'svwap', name: 'Session VWAP', type: 'overlay' },\n { id: 'ichimoku', name: 'Ichimoku Cloud', type: 'overlay' },\n { id: 'psar', name: 'Parabolic SAR', type: 'overlay' },\n { id: 'supertrend', name: 'Supertrend', type: 'overlay' },\n { id: 'keltner', name: 'Keltner Channel', type: 'overlay' },\n { id: 'donchian', name: 'Donchian Channel', type: 'overlay' },\n { id: 'pivots', name: 'Pivot Points', type: 'overlay' },\n { id: 'zigzag', name: 'ZigZag', type: 'overlay' },\n { id: 'lrc', name: 'Linear Regression Channel', type: 'overlay' },\n { id: 'chandelier', name: 'Chandelier Exit', type: 'overlay' },\n { id: 'alligator', name: 'Alligator', type: 'overlay' },\n { id: 'rsi', name: 'RSI', type: 'panel' },\n { id: 'macd', name: 'MACD', type: 'panel' },\n { id: 'stochastic', name: 'Stochastic', type: 'panel' },\n { id: 'atr', name: 'ATR', type: 'panel' },\n { id: 'adx', name: 'ADX', type: 'panel' },\n { id: 'obv', name: 'OBV', type: 'panel' },\n { id: 'williamsR', name: 'Williams %R', type: 'panel' },\n { id: 'cci', name: 'CCI', type: 'panel' },\n { id: 'mfi', name: 'MFI', type: 'panel' },\n { id: 'roc', name: 'ROC', type: 'panel' },\n { id: 'tsi', name: 'TSI', type: 'panel' },\n { id: 'cmf', name: 'CMF', type: 'panel' },\n { id: 'aroon', name: 'Aroon', type: 'panel' },\n { id: 'stddev', name: 'Std Deviation', type: 'panel' },\n { id: 'vroc', name: 'Volume ROC', type: 'panel' },\n { id: 'ad', name: 'Acc/Dist', type: 'panel' },\n { id: 'ao', name: 'Awesome Oscillator', type: 'panel' },\n { id: 'chaikinOsc', name: 'Chaikin Oscillator', type: 'panel' },\n { id: 'voldelta', name: 'Volume Delta', type: 'panel' },\n { id: 'vortex', name: 'Vortex Indicator', type: 'panel' },\n { id: 'chop', name: 'Choppiness Index', type: 'panel' },\n { id: 'uo', name: 'Ultimate Oscillator', type: 'panel' },\n { id: 'fi', name: 'Force Index', type: 'panel' },\n { id: 'crsi', name: 'Connors RSI', type: 'panel' },\n { id: 'coppock', name: 'Coppock Curve', type: 'panel' },\n { id: 'kst', name: 'Know Sure Thing', type: 'panel' },\n { id: 'elderray', name: 'Elder Ray', type: 'panel' },\n { id: 'stc', name: 'Schaff Trend Cycle', type: 'panel' },\n { id: 'kvo', name: 'Klinger Oscillator', type: 'panel' },\n { id: 'fisher', name: 'Fisher Transform', type: 'panel' },\n { id: 'dpo', name: 'Detrended Price Osc', type: 'panel' },\n { id: 'bop', name: 'Balance of Power', type: 'panel' },\n { id: 'massindex', name: 'Mass Index', type: 'panel' },\n { id: 'cmo', name: 'Chande Momentum', type: 'panel' },\n { id: 'trix', name: 'TRIX', type: 'panel' },\n { id: 'emv', name: 'Ease of Movement', type: 'panel' },\n { id: 'pvt', name: 'Price Volume Trend', type: 'panel' },\n { id: 'wad', name: 'Williams A/D', type: 'panel' },\n { id: 'chaikinvol', name: 'Chaikin Volatility', type: 'panel' },\n { id: 'rvi', name: 'Relative Vigor Index', type: 'panel' },\n { id: 'stochrsi', name: 'Stochastic RSI', type: 'panel' },\n { id: 'ppo', name: 'Percentage Price Oscillator', type: 'panel' },\n { id: 'ac', name: 'Accelerator Oscillator', type: 'panel' },\n { id: 'rmi', name: 'Relative Momentum Index', type: 'panel' },\n { id: 'disparity', name: 'Disparity Index', type: 'panel' },\n { id: 'qstick', name: 'Qstick', type: 'panel' },\n { id: 'pgo', name: 'Pretty Good Oscillator', type: 'panel' },\n { id: 'volumeProfile', name: 'Volume Profile', type: 'panel' },\n];\n\nexport const POPULAR_INDICATORS = [\n 'sma', 'ema', 'bb', 'rsi', 'macd', 'stochastic',\n 'vwap', 'atr', 'obv', 'ichimoku',\n];\n\nexport const DEFAULT_SYMBOLS = [\n 'BTCUSDT', 'ETHUSDT', 'SOLUSDT', 'BNBUSDT',\n];\n\nexport const DEFAULT_SETTINGS: ChartSettingsState = {\n candleUpColor: '#26A69A',\n candleDownColor: '#EF5350',\n candleUpWick: '#26A69A',\n candleDownWick: '#EF5350',\n backgroundColor: '#131722',\n gridColor: '#1E222D',\n gridVisible: true,\n volumeVisible: true,\n volumeProfileVisible: false,\n marketProfileVisible: false,\n marketProfileSplit: false,\n marketProfileLetters: false,\n marketProfileBuckets: 48,\n marketProfileOpacity: 0.32,\n depthHeatmapVisible: false,\n depthHeatmapOpacity: 0.7,\n sessionShadingVisible: false,\n pivotMarkersVisible: false,\n pivotStrength: 5,\n pivotStructureLabels: false,\n periodLevelsVisible: false,\n periodLevelsPeriod: 'day',\n legendVisible: true,\n barCountdown: true,\n logScale: false,\n scaleMode: 'regular',\n autoScale: true,\n crosshairMode: 'magnet',\n numberLocale: 'en-US',\n timezone: 'local',\n};\n","import widgetCss from './WidgetStyles.css?raw';\r\n\r\nlet refCount = 0;\r\nconst STYLE_ID = 'tcw-styles';\r\n\r\n/**\r\n * Inject the widget stylesheet into `document.head`. Reference-counted so\r\n * multiple `ChartWidget` instances share the same `<style>` tag and the last\r\n * to detach removes it. CSS lives in a sibling `.css` file and is inlined at\r\n * build time via Vite's `?raw` query — consumers see a plain string at runtime.\r\n */\r\nexport function injectWidgetStyles(): void {\r\n refCount++;\r\n if (refCount > 1) return;\r\n if (document.getElementById(STYLE_ID)) return;\r\n\r\n const style = document.createElement('style');\r\n style.id = STYLE_ID;\r\n style.textContent = widgetCss;\r\n document.head.appendChild(style);\r\n}\r\n\r\nexport function removeWidgetStyles(): void {\r\n refCount--;\r\n if (refCount > 0) return;\r\n\r\n const style = document.getElementById(STYLE_ID);\r\n if (style) {\r\n style.remove();\r\n }\r\n}\r\n","const ICON_PATHS: Record<string, string> = {\n cursor: '<path d=\"M3 3l7.07 16.97 2.51-7.39 7.39-2.51L3 3z\"/><path d=\"M13 13l6 6\"/>',\n trendingUp: '<polyline points=\"22 7 13.5 15.5 8.5 10.5 2 17\"/><polyline points=\"16 7 22 7 22 13\"/>',\n minus: '<path d=\"M5 12h14\"/>',\n penLine: '<path d=\"M12 20h9\"/><path d=\"M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z\"/>',\n hash: '<line x1=\"4\" y1=\"9\" x2=\"20\" y2=\"9\"/><line x1=\"4\" y1=\"15\" x2=\"20\" y2=\"15\"/><line x1=\"10\" y1=\"3\" x2=\"8\" y2=\"21\"/><line x1=\"16\" y1=\"3\" x2=\"14\" y2=\"21\"/>',\n square: '<rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\"/>',\n gitBranch: '<line x1=\"6\" y1=\"3\" x2=\"6\" y2=\"15\"/><circle cx=\"18\" cy=\"6\" r=\"3\"/><circle cx=\"6\" cy=\"18\" r=\"3\"/><path d=\"M18 9a9 9 0 0 1-9 9\"/>',\n ruler: '<path d=\"M21.3 15.3a2.4 2.4 0 0 1 0 3.4l-2.6 2.6a2.4 2.4 0 0 1-3.4 0L2.7 8.7a2.41 2.41 0 0 1 0-3.4l2.6-2.6a2.41 2.41 0 0 1 3.4 0Z\"/><path d=\"m14.5 12.5 2-2\"/><path d=\"m11.5 9.5 2-2\"/><path d=\"m8.5 6.5 2-2\"/><path d=\"m17.5 15.5 2-2\"/>',\n type: '<polyline points=\"4 7 4 4 20 4 20 7\"/><line x1=\"9\" y1=\"20\" x2=\"15\" y2=\"20\"/><line x1=\"12\" y1=\"4\" x2=\"12\" y2=\"20\"/>',\n magnet: '<path d=\"m6 15-4-4 6.75-6.77a7.79 7.79 0 0 1 11 11L13 22l-4-4 6.39-6.36a2.14 2.14 0 0 0-3-3L6 15\"/><path d=\"m5 8 4 4\"/><path d=\"m12 15 4 4\"/>',\n undo: '<path d=\"M3 7v6h6\"/><path d=\"M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13\"/>',\n redo: '<path d=\"M21 7v6h-6\"/><path d=\"M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3L21 13\"/>',\n trash: '<path d=\"M3 6h18\"/><path d=\"M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6\"/><path d=\"M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2\"/><line x1=\"10\" y1=\"11\" x2=\"10\" y2=\"17\"/><line x1=\"14\" y1=\"11\" x2=\"14\" y2=\"17\"/>',\n camera: '<path d=\"M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z\"/><circle cx=\"12\" cy=\"13\" r=\"3\"/>',\n settings: '<path d=\"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/>',\n moon: '<path d=\"M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z\"/>',\n sun: '<circle cx=\"12\" cy=\"12\" r=\"4\"/><path d=\"M12 2v2\"/><path d=\"M12 20v2\"/><path d=\"m4.93 4.93 1.41 1.41\"/><path d=\"m17.66 17.66 1.41 1.41\"/><path d=\"M2 12h2\"/><path d=\"M20 12h2\"/><path d=\"m6.34 17.66-1.41 1.41\"/><path d=\"m19.07 4.93-1.41 1.41\"/>',\n chevronDown: '<path d=\"m6 9 6 6 6-6\"/>',\n chevronUp: '<path d=\"m18 15-6-6-6 6\"/>',\n barChart: '<line x1=\"12\" y1=\"20\" x2=\"12\" y2=\"10\"/><line x1=\"18\" y1=\"20\" x2=\"18\" y2=\"4\"/><line x1=\"6\" y1=\"20\" x2=\"6\" y2=\"16\"/>',\n x: '<path d=\"M18 6 6 18\"/><path d=\"m6 6 12 12\"/>',\n play: '<polygon points=\"6 3 20 12 6 21 6 3\"/>',\n pause: '<rect width=\"4\" height=\"16\" x=\"6\" y=\"4\"/><rect width=\"4\" height=\"16\" x=\"14\" y=\"4\"/>',\n stop: '<rect width=\"14\" height=\"14\" x=\"5\" y=\"5\" rx=\"1\"/>',\n receipt: '<path d=\"M4 2v20l2-1 2 1 2-1 2 1 2-1 2 1 2-1 2 1V2l-2 1-2-1-2 1-2-1-2 1-2-1-2 1Z\"/><path d=\"M16 8h-6a2 2 0 1 0 0 4h4a2 2 0 1 1 0 4H8\"/><path d=\"M12 17.5v-11\"/>',\n bell: '<path d=\"M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9\"/><path d=\"M10.3 21a1.94 1.94 0 0 0 3.4 0\"/>',\n plus: '<path d=\"M5 12h14\"/><path d=\"M12 5v14\"/>',\n layers: '<path d=\"m12 2 9 5-9 5-9-5 9-5Z\"/><path d=\"m3 12 9 5 9-5\"/><path d=\"m3 17 9 5 9-5\"/>',\n eye: '<path d=\"M2 12s3.5-7 10-7 10 7 10 7-3.5 7-10 7-10-7-10-7Z\"/><circle cx=\"12\" cy=\"12\" r=\"3\"/>',\n eyeOff: '<path d=\"M9.9 4.24A9.12 9.12 0 0 1 12 4c6.5 0 10 7 10 7a13.2 13.2 0 0 1-1.67 2.68\"/><path d=\"M6.6 6.6A13.06 13.06 0 0 0 2 11s3.5 7 10 7a9.1 9.1 0 0 0 5.4-1.6\"/><path d=\"m2 2 20 20\"/>',\n lock: '<rect width=\"18\" height=\"11\" x=\"3\" y=\"11\" rx=\"2\"/><path d=\"M7 11V7a5 5 0 0 1 10 0v4\"/>',\n unlock: '<rect width=\"18\" height=\"11\" x=\"3\" y=\"11\" rx=\"2\"/><path d=\"M7 11V7a5 5 0 0 1 9.9-1\"/>',\n palette: '<circle cx=\"13.5\" cy=\"6.5\" r=\".5\" fill=\"currentColor\"/><circle cx=\"17.5\" cy=\"10.5\" r=\".5\" fill=\"currentColor\"/><circle cx=\"8.5\" cy=\"7.5\" r=\".5\" fill=\"currentColor\"/><circle cx=\"6.5\" cy=\"12.5\" r=\".5\" fill=\"currentColor\"/><path d=\"M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2Z\"/>',\n trendingDown: '<polyline points=\"22 17 13.5 8.5 8.5 13.5 2 7\"/><polyline points=\"16 17 22 17 22 11\"/>',\n check: '<polyline points=\"20 6 9 17 4 12\"/>',\n ladder: '<rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\"/><line x1=\"12\" y1=\"3\" x2=\"12\" y2=\"21\"/><line x1=\"3\" y1=\"8\" x2=\"21\" y2=\"8\"/><line x1=\"3\" y1=\"13\" x2=\"21\" y2=\"13\"/><line x1=\"3\" y1=\"18\" x2=\"21\" y2=\"18\"/>',\n};\n\nexport function createIcon(name: string, size = 14): string {\n const paths = ICON_PATHS[name];\n if (!paths) return '';\n return `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"${size}\" height=\"${size}\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\">${paths}</svg>`;\n}\n","export class WidgetDropdown {\n private trigger: HTMLElement;\n private panel: HTMLDivElement;\n private _isOpen = false;\n private onOutsideClick: (e: MouseEvent) => void;\n private onEscapeKey: (e: KeyboardEvent) => void;\n private onTriggerClick: () => void;\n\n constructor(trigger: HTMLElement, config: { width?: string; align?: 'left' | 'right' } = {}) {\n this.trigger = trigger;\n\n this.panel = document.createElement('div');\n this.panel.className = 'tcw-dropdown';\n this.panel.style.width = config.width ?? '200px';\n if (config.align === 'right') {\n this.panel.style.right = '0';\n } else {\n this.panel.style.left = '0';\n }\n this.panel.style.display = 'none';\n\n // Position relative to trigger\n trigger.style.position = 'relative';\n trigger.appendChild(this.panel);\n\n this.onTriggerClick = () => {\n if (this._isOpen) {\n this.close();\n } else {\n this.open();\n }\n };\n\n this.onOutsideClick = (e: MouseEvent) => {\n if (!this.trigger.contains(e.target as Node)) {\n this.close();\n }\n };\n\n this.onEscapeKey = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n this.close();\n }\n };\n\n trigger.addEventListener('click', this.onTriggerClick);\n }\n\n setContent(html: string): void {\n this.panel.innerHTML = html;\n }\n\n open(): void {\n if (this._isOpen) return;\n this._isOpen = true;\n this.panel.style.display = '';\n document.addEventListener('mousedown', this.onOutsideClick);\n document.addEventListener('keydown', this.onEscapeKey);\n }\n\n close(): void {\n if (!this._isOpen) return;\n this._isOpen = false;\n this.panel.style.display = 'none';\n document.removeEventListener('mousedown', this.onOutsideClick);\n document.removeEventListener('keydown', this.onEscapeKey);\n }\n\n isOpen(): boolean {\n return this._isOpen;\n }\n\n destroy(): void {\n this.trigger.removeEventListener('click', this.onTriggerClick);\n document.removeEventListener('mousedown', this.onOutsideClick);\n document.removeEventListener('keydown', this.onEscapeKey);\n this.panel.remove();\n }\n}\n","import type { ChartType } from '@tradecanvas/commons';\nimport type { ToolbarConfig, ToolbarCallbacks, WidgetState, ActiveIndicator } from './types.js';\nimport { createIcon } from './icons.js';\nimport { WidgetDropdown } from './WidgetDropdown.js';\n\nexport class WidgetToolbar {\n private config: ToolbarConfig;\n private callbacks: ToolbarCallbacks;\n private el: HTMLDivElement;\n private chartTypeDropdown: WidgetDropdown | null = null;\n private indicatorDropdown: WidgetDropdown | null = null;\n private tfButtons: HTMLButtonElement[] = [];\n private chipsContainer: HTMLDivElement | null = null;\n private themeBtn: HTMLButtonElement | null = null;\n\n constructor(host: HTMLElement, config: ToolbarConfig, callbacks: ToolbarCallbacks) {\n this.config = config;\n this.callbacks = callbacks;\n this.el = document.createElement('div');\n this.el.className = 'tcw-toolbar';\n this.build();\n host.appendChild(this.el);\n }\n\n private build(): void {\n const { config, callbacks, el } = this;\n\n // Symbol button\n const symbolBtn = document.createElement('button');\n symbolBtn.className = 'tcw-toolbar-symbol';\n symbolBtn.dataset.role = 'symbol';\n symbolBtn.addEventListener('click', callbacks.onSymbolClick);\n el.appendChild(symbolBtn);\n el.appendChild(this.sep());\n\n // Timeframes\n const tfGroup = document.createElement('div');\n tfGroup.className = 'tcw-toolbar-group';\n for (const tf of config.timeframes) {\n const btn = document.createElement('button');\n btn.className = 'tcw-btn';\n btn.textContent = tf.label;\n btn.dataset.tf = tf.value;\n btn.addEventListener('click', () => callbacks.onTimeframe(tf.value));\n tfGroup.appendChild(btn);\n this.tfButtons.push(btn);\n }\n el.appendChild(tfGroup);\n el.appendChild(this.sep());\n\n // Chart type dropdown\n const ctWrap = document.createElement('div');\n ctWrap.style.position = 'relative';\n ctWrap.style.display = 'inline-flex';\n\n const ctTrigger = document.createElement('button');\n ctTrigger.className = 'tcw-dropdown-trigger';\n ctTrigger.dataset.role = 'charttype';\n ctWrap.appendChild(ctTrigger);\n el.appendChild(ctWrap);\n\n this.chartTypeDropdown = new WidgetDropdown(ctWrap, { width: '160px' });\n this.buildChartTypeMenu();\n\n el.appendChild(this.sep());\n\n // Indicators dropdown\n const indWrap = document.createElement('div');\n indWrap.style.position = 'relative';\n indWrap.style.display = 'inline-flex';\n\n const indTrigger = document.createElement('button');\n indTrigger.className = 'tcw-dropdown-trigger';\n indTrigger.dataset.role = 'indicators';\n indWrap.appendChild(indTrigger);\n el.appendChild(indWrap);\n\n this.indicatorDropdown = new WidgetDropdown(indWrap, { width: '280px' });\n this.buildIndicatorMenu();\n\n // Indicator chips\n this.chipsContainer = document.createElement('div');\n this.chipsContainer.className = 'tcw-indicator-chips';\n el.appendChild(this.chipsContainer);\n\n // Spacer\n el.appendChild(this.spacer());\n\n // Right side buttons\n if (callbacks.onToggleReplay) {\n const replayBtn = this.iconBtn('play', 'Bar replay', callbacks.onToggleReplay);\n replayBtn.dataset.role = 'replay';\n el.appendChild(replayBtn);\n }\n\n if (callbacks.onBracket) {\n const onBracket = callbacks.onBracket;\n const longBtn = this.iconBtn('trendingUp', 'Long bracket', () => onBracket('buy'));\n longBtn.dataset.role = 'long';\n longBtn.classList.add('tcw-btn-long');\n el.appendChild(longBtn);\n const shortBtn = this.iconBtn('trendingDown', 'Short bracket', () => onBracket('sell'));\n shortBtn.dataset.role = 'short';\n shortBtn.classList.add('tcw-btn-short');\n el.appendChild(shortBtn);\n }\n\n if (callbacks.onToggleLadder) {\n const ladderBtn = this.iconBtn('ladder', 'Depth ladder', callbacks.onToggleLadder);\n ladderBtn.dataset.role = 'ladder';\n el.appendChild(ladderBtn);\n }\n\n if (callbacks.onToggleObjects) {\n const objectsBtn = this.iconBtn('layers', 'Objects', callbacks.onToggleObjects);\n objectsBtn.dataset.role = 'objects';\n el.appendChild(objectsBtn);\n }\n\n if (callbacks.onToggleAlerts) {\n const alertsBtn = this.iconBtn('bell', 'Price alerts', callbacks.onToggleAlerts);\n alertsBtn.dataset.role = 'alerts';\n el.appendChild(alertsBtn);\n }\n\n const screenshotBtn = this.iconBtn('camera', 'Screenshot', callbacks.onScreenshot);\n el.appendChild(screenshotBtn);\n\n const settingsBtn = this.iconBtn('settings', 'Chart Settings', callbacks.onSettings);\n el.appendChild(settingsBtn);\n\n this.themeBtn = this.iconBtn('moon', 'Toggle theme', callbacks.onToggleTheme);\n this.themeBtn.dataset.role = 'theme';\n el.appendChild(this.themeBtn);\n }\n\n private buildChartTypeMenu(): void {\n if (!this.chartTypeDropdown) return;\n const items = this.config.chartTypes.map(ct =>\n `<button class=\"tcw-dropdown-item\" data-ct=\"${ct.value}\">${ct.label}</button>`\n ).join('');\n this.chartTypeDropdown.setContent(items);\n\n // Attach events to items after content set\n const panel = this.chartTypeDropdown['panel'] as HTMLDivElement;\n panel.querySelectorAll('.tcw-dropdown-item').forEach((btn) => {\n btn.addEventListener('click', (e) => {\n const value = (e.currentTarget as HTMLElement).dataset.ct as ChartType;\n this.callbacks.onChartType(value);\n this.chartTypeDropdown?.close();\n });\n });\n }\n\n private buildIndicatorMenu(): void {\n if (!this.indicatorDropdown) return;\n const { indicators, popularIndicatorIds } = this.config;\n\n const popular = indicators.filter(d => popularIndicatorIds.includes(d.id));\n const other = indicators.filter(d => !popularIndicatorIds.includes(d.id));\n\n let html = '<div class=\"tcw-dropdown-label\">Popular</div>';\n for (const ind of popular) {\n html += `<button class=\"tcw-dropdown-item\" data-ind=\"${ind.id}\"><span>${ind.name}</span><span class=\"tcw-tag\">${ind.type}</span></button>`;\n }\n html += '<div class=\"tcw-dropdown-divider\"></div>';\n html += '<div class=\"tcw-dropdown-label\">All</div>';\n for (const ind of other) {\n html += `<button class=\"tcw-dropdown-item\" data-ind=\"${ind.id}\"><span>${ind.name}</span><span class=\"tcw-tag\">${ind.type}</span></button>`;\n }\n\n this.indicatorDropdown.setContent(html);\n\n const panel = this.indicatorDropdown['panel'] as HTMLDivElement;\n panel.querySelectorAll('.tcw-dropdown-item[data-ind]').forEach((btn) => {\n btn.addEventListener('click', (e) => {\n const id = (e.currentTarget as HTMLElement).dataset.ind!;\n this.callbacks.onAddIndicator(id);\n });\n });\n }\n\n update(state: WidgetState): void {\n // Symbol\n const symbolBtn = this.el.querySelector('[data-role=\"symbol\"]') as HTMLButtonElement | null;\n if (symbolBtn) symbolBtn.textContent = state.symbol;\n\n // Timeframe buttons\n for (const btn of this.tfButtons) {\n btn.classList.toggle('tcw-active', btn.dataset.tf === state.timeframe);\n }\n\n // Chart type trigger label\n const ctTrigger = this.el.querySelector('[data-role=\"charttype\"]') as HTMLElement | null;\n if (ctTrigger) {\n const label = this.config.chartTypes.find(t => t.value === state.chartType)?.label ?? 'Candles';\n ctTrigger.innerHTML = `${createIcon('barChart', 14)} ${label} ${createIcon('chevronDown', 12)}`;\n }\n\n // Indicator trigger + badge\n const indTrigger = this.el.querySelector('[data-role=\"indicators\"]') as HTMLElement | null;\n if (indTrigger) {\n const count = state.activeIndicators.size;\n let inner = `${createIcon('trendingUp', 14)} Indicators`;\n if (count > 0) {\n inner += ` <span class=\"tcw-badge-count\">${count}</span>`;\n }\n indTrigger.innerHTML = inner;\n }\n\n // Chips\n if (this.chipsContainer) {\n const activeList = this.getActiveIndicatorList(state);\n this.chipsContainer.innerHTML = '';\n for (const ind of activeList) {\n const chip = document.createElement('div');\n chip.className = 'tcw-indicator-chip';\n\n const label = document.createElement('span');\n label.textContent = ind.label;\n chip.appendChild(label);\n\n const removeBtn = document.createElement('button');\n removeBtn.className = 'tcw-chip-remove';\n removeBtn.innerHTML = createIcon('x', 10);\n removeBtn.addEventListener('click', () => this.callbacks.onRemoveIndicator(ind.instanceId));\n chip.appendChild(removeBtn);\n\n this.chipsContainer.appendChild(chip);\n }\n }\n\n // Theme toggle icon\n if (this.themeBtn) {\n this.themeBtn.innerHTML = state.isDark ? createIcon('moon', 14) : createIcon('sun', 14);\n }\n }\n\n private getActiveIndicatorList(state: WidgetState): ActiveIndicator[] {\n const result: ActiveIndicator[] = [];\n for (const [id, instanceId] of state.activeIndicators.entries()) {\n result.push({ instanceId, id, label: id.toUpperCase() });\n }\n return result;\n }\n\n private sep(): HTMLSpanElement {\n const s = document.createElement('span');\n s.className = 'tcw-toolbar-sep';\n return s;\n }\n\n private spacer(): HTMLSpanElement {\n const s = document.createElement('span');\n s.className = 'tcw-toolbar-spacer';\n return s;\n }\n\n private iconBtn(icon: string, title: string, onClick: () => void): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.className = 'tcw-btn-icon';\n btn.title = title;\n btn.innerHTML = createIcon(icon, 14);\n btn.addEventListener('click', onClick);\n return btn;\n }\n\n destroy(): void {\n this.chartTypeDropdown?.destroy();\n this.indicatorDropdown?.destroy();\n this.el.remove();\n }\n}\n","import type { SidebarConfig, SidebarCallbacks, WidgetState } from './types.js';\nimport { createIcon } from './icons.js';\n\nconst GROUP_ICONS = [\n 'trendingUp', 'minus', 'penLine', 'hash', 'square', 'gitBranch', 'ruler', 'type',\n];\n\n/** Icon for a drawing tool in the favorites strip — falls back to a pen. */\nconst TOOL_ICONS: Record<string, string> = {\n trendLine: 'trendingUp', ray: 'trendingUp', extendedLine: 'trendingUp',\n horizontalLine: 'minus', verticalLine: 'penLine',\n rectangle: 'square', ellipse: 'square', triangle: 'square', arrow: 'trendingUp',\n parallelChannel: 'gitBranch', regressionChannel: 'gitBranch', pitchfork: 'gitBranch',\n fibRetracement: 'hash', fibExtension: 'hash', fibTimeZones: 'hash',\n gannBox: 'hash', gannFan: 'gitBranch', elliottWave: 'trendingUp',\n priceRange: 'ruler', dateRange: 'ruler', measure: 'ruler',\n textAnnotation: 'type', anchoredVWAP: 'trendingUp', volumeProfileRange: 'barChart',\n};\n\nfunction toolIcon(tool: string): string {\n return TOOL_ICONS[tool] ?? 'penLine';\n}\n\n/** Human label for a tool id, sourced from the configured groups. */\nfunction toolLabel(groups: SidebarConfig['drawingToolGroups'], tool: string): string {\n for (const g of groups) {\n const t = g.tools.find((x) => x.value === tool);\n if (t) return t.label;\n }\n return tool;\n}\n\nexport class WidgetDrawingSidebar {\n private config: SidebarConfig;\n private callbacks: SidebarCallbacks;\n private el: HTMLDivElement;\n private groupWraps: HTMLDivElement[] = [];\n private groupButtons: HTMLButtonElement[] = [];\n private cursorBtn: HTMLButtonElement | null = null;\n private magnetBtn: HTMLButtonElement | null = null;\n private flyoutEl: HTMLDivElement | null = null;\n private favoritesEl: HTMLDivElement | null = null;\n private favoritesDivider: HTMLDivElement | null = null;\n private favorites: string[] = [];\n\n constructor(host: HTMLElement, config: SidebarConfig, callbacks: SidebarCallbacks) {\n this.config = config;\n this.callbacks = callbacks;\n this.el = document.createElement('div');\n this.el.className = 'tcw-sidebar';\n this.build();\n host.appendChild(this.el);\n }\n\n private build(): void {\n const { config, callbacks, el } = this;\n\n // Cursor button\n this.cursorBtn = document.createElement('button');\n this.cursorBtn.className = 'tcw-sidebar-btn';\n this.cursorBtn.title = 'Cursor';\n this.cursorBtn.innerHTML = createIcon('cursor', 14);\n this.cursorBtn.addEventListener('click', callbacks.onCancelDrawing);\n el.appendChild(this.cursorBtn);\n\n el.appendChild(this.divider());\n\n // Favorites strip (pinned tools) — only when favorites are enabled.\n if (callbacks.onToggleFavorite) {\n this.favorites = [...(config.favorites ?? [])];\n this.favoritesEl = document.createElement('div');\n this.favoritesEl.className = 'tcw-sidebar-favorites';\n el.appendChild(this.favoritesEl);\n this.favoritesDivider = this.divider();\n el.appendChild(this.favoritesDivider);\n this.renderFavorites();\n }\n\n // Tool groups\n config.drawingToolGroups.forEach((group, idx) => {\n const wrap = document.createElement('div');\n wrap.className = 'tcw-tool-group-wrap';\n\n const btn = document.createElement('button');\n btn.className = 'tcw-sidebar-btn';\n btn.title = group.label;\n btn.innerHTML = createIcon(GROUP_ICONS[idx] ?? 'square', 14);\n\n if (group.tools.length > 1) {\n const dot = document.createElement('span');\n dot.className = 'tcw-multi-dot';\n btn.appendChild(dot);\n }\n\n btn.addEventListener('click', () => callbacks.onDrawingTool(group.tools[0].value));\n wrap.appendChild(btn);\n\n // Flyout events via JS (not CSS hover)\n wrap.addEventListener('mouseenter', () => this.showFlyout(idx));\n wrap.addEventListener('mouseleave', () => this.hideFlyout());\n\n el.appendChild(wrap);\n this.groupWraps.push(wrap);\n this.groupButtons.push(btn);\n });\n\n // Spacer\n const spacer = document.createElement('div');\n spacer.className = 'tcw-sidebar-spacer';\n el.appendChild(spacer);\n\n el.appendChild(this.divider());\n\n // Bottom tools\n if (callbacks.onToggleStyle) {\n const styleBtn = document.createElement('button');\n styleBtn.className = 'tcw-sidebar-btn';\n styleBtn.title = 'Drawing style & templates';\n styleBtn.dataset.role = 'style';\n styleBtn.innerHTML = createIcon('palette', 14);\n styleBtn.addEventListener('click', callbacks.onToggleStyle);\n el.appendChild(styleBtn);\n }\n\n this.magnetBtn = document.createElement('button');\n this.magnetBtn.className = 'tcw-sidebar-btn';\n this.magnetBtn.title = 'Magnet';\n this.magnetBtn.innerHTML = createIcon('magnet', 14);\n this.magnetBtn.addEventListener('click', callbacks.onToggleMagnet);\n el.appendChild(this.magnetBtn);\n\n const undoBtn = document.createElement('button');\n undoBtn.className = 'tcw-sidebar-btn';\n undoBtn.title = 'Undo';\n undoBtn.innerHTML = createIcon('undo', 14);\n undoBtn.addEventListener('click', callbacks.onUndo);\n el.appendChild(undoBtn);\n\n const redoBtn = document.createElement('button');\n redoBtn.className = 'tcw-sidebar-btn';\n redoBtn.title = 'Redo';\n redoBtn.innerHTML = createIcon('redo', 14);\n redoBtn.addEventListener('click', callbacks.onRedo);\n el.appendChild(redoBtn);\n\n const clearBtn = document.createElement('button');\n clearBtn.className = 'tcw-sidebar-btn tcw-danger';\n clearBtn.title = 'Clear all';\n clearBtn.innerHTML = createIcon('trash', 14);\n clearBtn.addEventListener('click', callbacks.onClearDrawings);\n el.appendChild(clearBtn);\n }\n\n /** Update the pinned-tools strip. */\n setFavorites(favorites: string[]): void {\n this.favorites = [...favorites];\n this.renderFavorites();\n }\n\n private renderFavorites(): void {\n if (!this.favoritesEl) return;\n this.favoritesEl.replaceChildren();\n const visible = this.favorites.length > 0;\n this.favoritesEl.style.display = visible ? '' : 'none';\n if (this.favoritesDivider) this.favoritesDivider.style.display = visible ? '' : 'none';\n\n for (const tool of this.favorites) {\n const btn = document.createElement('button');\n btn.className = 'tcw-sidebar-btn';\n btn.title = `${toolLabel(this.config.drawingToolGroups, tool)} (right-click to unpin)`;\n btn.dataset.toolValue = tool;\n btn.innerHTML = createIcon(toolIcon(tool), 14);\n btn.addEventListener('click', () => this.callbacks.onDrawingTool(tool as never));\n btn.addEventListener('contextmenu', (e) => {\n e.preventDefault();\n this.callbacks.onToggleFavorite?.(tool as never);\n });\n this.favoritesEl.appendChild(btn);\n }\n }\n\n private showFlyout(idx: number): void {\n const group = this.config.drawingToolGroups[idx];\n if (!group || group.tools.length <= 1) return;\n\n this.hideFlyout();\n\n const flyout = document.createElement('div');\n flyout.className = 'tcw-flyout';\n\n const header = document.createElement('div');\n header.className = 'tcw-flyout-header';\n header.textContent = group.label;\n flyout.appendChild(header);\n\n for (const tool of group.tools) {\n const item = document.createElement('button');\n item.className = 'tcw-flyout-item';\n item.textContent = tool.label;\n item.dataset.toolValue = tool.value;\n item.addEventListener('click', () => {\n this.callbacks.onDrawingTool(tool.value);\n this.hideFlyout();\n });\n if (this.callbacks.onToggleFavorite) {\n if (this.favorites.includes(tool.value)) item.classList.add('tcw-flyout-faved');\n item.title = 'Right-click to pin/unpin';\n item.addEventListener('contextmenu', (e) => {\n e.preventDefault();\n this.callbacks.onToggleFavorite?.(tool.value);\n });\n }\n flyout.appendChild(item);\n }\n\n this.flyoutEl = flyout;\n this.groupWraps[idx].appendChild(flyout);\n }\n\n private hideFlyout(): void {\n if (this.flyoutEl) {\n this.flyoutEl.remove();\n this.flyoutEl = null;\n }\n }\n\n update(state: WidgetState): void {\n // Cursor active\n if (this.cursorBtn) {\n this.cursorBtn.classList.toggle('tcw-active', state.activeTool === null);\n }\n\n // Group buttons\n const { drawingToolGroups } = this.config;\n for (let i = 0; i < drawingToolGroups.length; i++) {\n const isActive = drawingToolGroups[i].tools.some(t => t.value === state.activeTool);\n this.groupButtons[i].classList.toggle('tcw-active', isActive);\n }\n\n // Flyout items\n if (this.flyoutEl) {\n this.flyoutEl.querySelectorAll('.tcw-flyout-item').forEach((item) => {\n const el = item as HTMLElement;\n el.classList.toggle('tcw-active', el.dataset.toolValue === state.activeTool);\n });\n }\n\n // Magnet\n if (this.magnetBtn) {\n this.magnetBtn.classList.toggle('tcw-active', state.magnetEnabled);\n this.magnetBtn.title = state.magnetEnabled ? 'Magnet ON' : 'Magnet OFF';\n }\n }\n\n private divider(): HTMLDivElement {\n const d = document.createElement('div');\n d.className = 'tcw-sidebar-divider';\n return d;\n }\n\n destroy(): void {\n this.hideFlyout();\n this.el.remove();\n }\n}\n","import type { ChartSettingsState, SettingsCallbacks } from './types.js';\nimport { createIcon } from './icons.js';\n\ntype Tab = 'style' | 'display' | 'scale';\nconst TABS: Tab[] = ['style', 'display', 'scale'];\n\nexport class WidgetSettings {\n private callbacks: SettingsCallbacks;\n private backdrop: HTMLDivElement | null = null;\n private modal: HTMLDivElement | null = null;\n private currentTab: Tab = 'style';\n private currentSettings: ChartSettingsState | null = null;\n private bodyEl: HTMLDivElement | null = null;\n private tabButtons: HTMLButtonElement[] = [];\n\n constructor(callbacks: SettingsCallbacks) {\n this.callbacks = callbacks;\n }\n\n open(currentSettings: ChartSettingsState): void {\n this.currentSettings = { ...currentSettings };\n this.currentTab = 'style';\n this.buildModal();\n }\n\n close(): void {\n this.backdrop?.remove();\n this.modal?.remove();\n this.backdrop = null;\n this.modal = null;\n this.bodyEl = null;\n this.tabButtons = [];\n }\n\n private buildModal(): void {\n // Backdrop\n this.backdrop = document.createElement('div');\n this.backdrop.className = 'tcw-modal-backdrop';\n this.backdrop.addEventListener('click', () => {\n this.callbacks.onClose();\n this.close();\n });\n document.body.appendChild(this.backdrop);\n\n // Modal\n this.modal = document.createElement('div');\n this.modal.className = 'tcw-modal';\n\n // Header\n const header = document.createElement('div');\n header.className = 'tcw-modal-header';\n const h3 = document.createElement('h3');\n h3.textContent = 'Chart Settings';\n header.appendChild(h3);\n const closeBtn = document.createElement('button');\n closeBtn.className = 'tcw-modal-close';\n closeBtn.innerHTML = createIcon('x', 16);\n closeBtn.addEventListener('click', () => {\n this.callbacks.onClose();\n this.close();\n });\n header.appendChild(closeBtn);\n this.modal.appendChild(header);\n\n // Tabs\n const tabsEl = document.createElement('div');\n tabsEl.className = 'tcw-modal-tabs';\n this.tabButtons = [];\n for (const tab of TABS) {\n const btn = document.createElement('button');\n btn.className = 'tcw-modal-tab';\n btn.textContent = tab;\n btn.dataset.tab = tab;\n if (tab === this.currentTab) btn.classList.add('tcw-active');\n btn.addEventListener('click', () => {\n this.currentTab = tab;\n this.tabButtons.forEach(b => b.classList.toggle('tcw-active', b.dataset.tab === tab));\n this.renderTabContent();\n });\n tabsEl.appendChild(btn);\n this.tabButtons.push(btn);\n }\n this.modal.appendChild(tabsEl);\n\n // Body\n this.bodyEl = document.createElement('div');\n this.bodyEl.className = 'tcw-modal-body';\n this.modal.appendChild(this.bodyEl);\n this.renderTabContent();\n\n // Footer\n const footer = document.createElement('div');\n footer.className = 'tcw-modal-footer';\n const resetBtn = document.createElement('button');\n resetBtn.className = 'tcw-reset-link';\n resetBtn.textContent = 'Reset to defaults';\n resetBtn.addEventListener('click', () => this.callbacks.onReset());\n footer.appendChild(resetBtn);\n const doneBtn = document.createElement('button');\n doneBtn.className = 'tcw-done-btn';\n doneBtn.textContent = 'Done';\n doneBtn.addEventListener('click', () => {\n this.callbacks.onClose();\n this.close();\n });\n footer.appendChild(doneBtn);\n this.modal.appendChild(footer);\n\n document.body.appendChild(this.modal);\n\n // Escape key\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Escape') {\n document.removeEventListener('keydown', onKeyDown);\n this.callbacks.onClose();\n this.close();\n }\n };\n document.addEventListener('keydown', onKeyDown);\n }\n\n private renderTabContent(): void {\n if (!this.bodyEl || !this.currentSettings) return;\n this.bodyEl.innerHTML = '';\n\n switch (this.currentTab) {\n case 'style':\n this.renderStyleTab();\n break;\n case 'display':\n this.renderDisplayTab();\n break;\n case 'scale':\n this.renderScaleTab();\n break;\n }\n }\n\n private renderStyleTab(): void {\n if (!this.bodyEl || !this.currentSettings) return;\n const s = this.currentSettings;\n\n // Candle Colors\n const candleSection = this.section('Candle Colors');\n candleSection.appendChild(this.colorRow('Up Body', s.candleUpColor, (v) => this.patch({ candleUpColor: v })));\n candleSection.appendChild(this.colorRow('Down Body', s.candleDownColor, (v) => this.patch({ candleDownColor: v })));\n candleSection.appendChild(this.colorRow('Up Wick', s.candleUpWick, (v) => this.patch({ candleUpWick: v })));\n candleSection.appendChild(this.colorRow('Down Wick', s.candleDownWick, (v) => this.patch({ candleDownWick: v })));\n this.bodyEl.appendChild(candleSection);\n\n // Background\n const bgSection = this.section('Background');\n bgSection.appendChild(this.colorRow('Background', s.backgroundColor, (v) => this.patch({ backgroundColor: v })));\n bgSection.appendChild(this.colorRow('Grid', s.gridColor, (v) => this.patch({ gridColor: v })));\n this.bodyEl.appendChild(bgSection);\n }\n\n private renderDisplayTab(): void {\n if (!this.bodyEl || !this.currentSettings) return;\n const s = this.currentSettings;\n\n const section = this.section();\n section.appendChild(this.toggleRow('Grid Lines', s.gridVisible, (v) => this.patch({ gridVisible: v })));\n section.appendChild(this.toggleRow('Volume', s.volumeVisible, (v) => this.patch({ volumeVisible: v })));\n section.appendChild(this.toggleRow('Volume Profile', s.volumeProfileVisible, (v) => this.patch({ volumeProfileVisible: v })));\n section.appendChild(this.toggleRow('Market Profile (TPO)', s.marketProfileVisible, (v) => this.patch({ marketProfileVisible: v })));\n section.appendChild(this.toggleRow('MP split by session', s.marketProfileSplit, (v) => this.patch({ marketProfileSplit: v })));\n section.appendChild(this.toggleRow('MP letters (TPO)', s.marketProfileLetters, (v) => this.patch({ marketProfileLetters: v })));\n section.appendChild(this.rangeRow('MP buckets', s.marketProfileBuckets, 8, 200, 1, (v) => this.patch({ marketProfileBuckets: v })));\n section.appendChild(this.rangeRow('MP opacity', s.marketProfileOpacity, 0.05, 1, 0.05, (v) => this.patch({ marketProfileOpacity: v }), (v) => `${Math.round(v * 100)}%`));\n section.appendChild(this.toggleRow('Liquidity heatmap', s.depthHeatmapVisible, (v) => this.patch({ depthHeatmapVisible: v })));\n section.appendChild(this.rangeRow('Heatmap opacity', s.depthHeatmapOpacity, 0.1, 1, 0.05, (v) => this.patch({ depthHeatmapOpacity: v }), (v) => `${Math.round(v * 100)}%`));\n section.appendChild(this.toggleRow('Swing markers', s.pivotMarkersVisible, (v) => this.patch({ pivotMarkersVisible: v })));\n section.appendChild(this.rangeRow('Swing strength', s.pivotStrength, 2, 20, 1, (v) => this.patch({ pivotStrength: v })));\n section.appendChild(this.toggleRow('Swing structure (HH/HL)', s.pivotStructureLabels, (v) => this.patch({ pivotStructureLabels: v })));\n section.appendChild(this.toggleRow('Session shading (RTH)', s.sessionShadingVisible, (v) => this.patch({ sessionShadingVisible: v })));\n section.appendChild(this.toggleRow('Prior-period levels', s.periodLevelsVisible, (v) => this.patch({ periodLevelsVisible: v })));\n section.appendChild(this.selectRow('Period levels basis', s.periodLevelsPeriod, [\n { value: 'day', label: 'Prior Day (PDH/PDL)' },\n { value: 'week', label: 'Prior Week (PWH/PWL)' },\n ], (v) => this.patch({ periodLevelsPeriod: v as ChartSettingsState['periodLevelsPeriod'] })));\n section.appendChild(this.toggleRow('OHLC Legend', s.legendVisible, (v) => this.patch({ legendVisible: v })));\n section.appendChild(this.toggleRow('Bar Countdown', s.barCountdown, (v) => this.patch({ barCountdown: v })));\n\n // Crosshair mode\n section.appendChild(this.selectRow('Crosshair Mode', s.crosshairMode, [\n { label: 'Magnet', value: 'magnet' },\n { label: 'Normal', value: 'normal' },\n { label: 'Hidden', value: 'hidden' },\n ], (v) => this.patch({ crosshairMode: v as ChartSettingsState['crosshairMode'] })));\n\n // Number locale\n section.appendChild(this.selectRow('Timezone', s.timezone, [\n { value: 'local', label: 'Local' },\n { value: '0', label: 'UTC / London' },\n { value: '-300', label: 'New York (UTC-5)' },\n { value: '-360', label: 'Chicago (UTC-6)' },\n { value: '60', label: 'Frankfurt (UTC+1)' },\n { value: '480', label: 'Singapore/HK (UTC+8)' },\n { value: '540', label: 'Tokyo (UTC+9)' },\n { value: '330', label: 'Mumbai (UTC+5:30)' },\n ], (v) => this.patch({ timezone: v })));\n section.appendChild(this.selectRow('Number Locale', s.numberLocale, [\n { label: 'en-US (65,234.00)', value: 'en-US' },\n { label: 'de-DE (65.234,00)', value: 'de-DE' },\n { label: 'fr-FR (65 234,00)', value: 'fr-FR' },\n { label: 'vi-VN (65.234,00)', value: 'vi-VN' },\n { label: 'en-IN (65,234.00)', value: 'en-IN' },\n { label: 'ja-JP (65,234.00)', value: 'ja-JP' },\n ], (v) => this.patch({ numberLocale: v })));\n\n this.bodyEl.appendChild(section);\n }\n\n private renderScaleTab(): void {\n if (!this.bodyEl || !this.currentSettings) return;\n const s = this.currentSettings;\n\n const section = this.section();\n section.appendChild(this.toggleRow('Auto Scale', s.autoScale, (v) => this.patch({ autoScale: v })));\n section.appendChild(this.selectRow('Price Scale', s.scaleMode, [\n { value: 'regular', label: 'Regular' },\n { value: 'logarithmic', label: 'Logarithmic' },\n { value: 'percentage', label: 'Percentage' },\n { value: 'indexedTo100', label: 'Indexed to 100' },\n ], (v) => this.patch({ scaleMode: v as ChartSettingsState['scaleMode'] })));\n this.bodyEl.appendChild(section);\n }\n\n private patch(partial: Partial<ChartSettingsState>): void {\n if (this.currentSettings) {\n Object.assign(this.currentSettings, partial);\n }\n this.callbacks.onChange(partial);\n }\n\n private section(title?: string): HTMLDivElement {\n const div = document.createElement('div');\n div.className = 'tcw-settings-section';\n if (title) {\n const t = document.createElement('div');\n t.className = 'tcw-settings-section-title';\n t.textContent = title;\n div.appendChild(t);\n }\n return div;\n }\n\n private colorRow(label: string, value: string, onChange: (v: string) => void): HTMLDivElement {\n const row = document.createElement('div');\n row.className = 'tcw-settings-row';\n\n const lbl = document.createElement('span');\n lbl.className = 'tcw-settings-label';\n lbl.textContent = label;\n row.appendChild(lbl);\n\n const wrap = document.createElement('div');\n wrap.className = 'tcw-color-picker-wrap';\n\n const input = document.createElement('input');\n input.type = 'color';\n input.value = value;\n\n const hex = document.createElement('span');\n hex.className = 'tcw-color-hex';\n hex.textContent = value;\n\n input.addEventListener('input', () => {\n hex.textContent = input.value;\n onChange(input.value);\n });\n\n wrap.appendChild(input);\n wrap.appendChild(hex);\n row.appendChild(wrap);\n return row;\n }\n\n private toggleRow(label: string, value: boolean, onChange: (v: boolean) => void): HTMLDivElement {\n const row = document.createElement('div');\n row.className = 'tcw-settings-row';\n\n const lbl = document.createElement('span');\n lbl.className = 'tcw-settings-label';\n lbl.textContent = label;\n row.appendChild(lbl);\n\n const toggle = document.createElement('button');\n toggle.className = `tcw-toggle${value ? ' tcw-on' : ''}`;\n toggle.addEventListener('click', () => {\n const newVal = !toggle.classList.contains('tcw-on');\n toggle.classList.toggle('tcw-on', newVal);\n onChange(newVal);\n });\n row.appendChild(toggle);\n return row;\n }\n\n private selectRow(\n label: string,\n value: string,\n options: { label: string; value: string }[],\n onChange: (v: string) => void,\n ): HTMLDivElement {\n const row = document.createElement('div');\n row.className = 'tcw-settings-row';\n\n const lbl = document.createElement('span');\n lbl.className = 'tcw-settings-label';\n lbl.textContent = label;\n row.appendChild(lbl);\n\n const select = document.createElement('select');\n select.className = 'tcw-settings-select';\n for (const opt of options) {\n const o = document.createElement('option');\n o.value = opt.value;\n o.textContent = opt.label;\n if (opt.value === value) o.selected = true;\n select.appendChild(o);\n }\n select.addEventListener('change', () => onChange(select.value));\n row.appendChild(select);\n return row;\n }\n\n private rangeRow(\n label: string,\n value: number,\n min: number,\n max: number,\n step: number,\n onChange: (v: number) => void,\n format: (v: number) => string = (v) => String(v),\n ): HTMLDivElement {\n const row = document.createElement('div');\n row.className = 'tcw-settings-row';\n\n const lbl = document.createElement('span');\n lbl.className = 'tcw-settings-label';\n lbl.textContent = label;\n row.appendChild(lbl);\n\n const wrap = document.createElement('div');\n wrap.className = 'tcw-settings-range';\n\n const input = document.createElement('input');\n input.type = 'range';\n input.min = String(min);\n input.max = String(max);\n input.step = String(step);\n input.value = String(value);\n\n const out = document.createElement('span');\n out.className = 'tcw-settings-range-val';\n out.textContent = format(value);\n\n input.addEventListener('input', () => {\n const v = Number(input.value);\n out.textContent = format(v);\n onChange(v);\n });\n\n wrap.appendChild(input);\n wrap.appendChild(out);\n row.appendChild(wrap);\n return row;\n }\n\n destroy(): void {\n this.close();\n }\n}\n","export class WidgetStatusBar {\n private el: HTMLDivElement;\n private dotEl: HTMLSpanElement;\n private messageEl: HTMLSpanElement;\n private infoEl: HTMLSpanElement;\n\n constructor(host: HTMLElement) {\n this.el = document.createElement('div');\n this.el.className = 'tcw-statusbar';\n\n const indicator = document.createElement('div');\n indicator.className = 'tcw-status-indicator';\n\n this.dotEl = document.createElement('span');\n this.dotEl.className = 'tcw-status-dot';\n indicator.appendChild(this.dotEl);\n\n this.messageEl = document.createElement('span');\n indicator.appendChild(this.messageEl);\n\n this.el.appendChild(indicator);\n\n this.infoEl = document.createElement('span');\n this.el.appendChild(this.infoEl);\n\n host.appendChild(this.el);\n }\n\n update(state: { connectionState: string; message: string; symbol: string; timeframe: string }): void {\n this.dotEl.className = 'tcw-status-dot';\n if (state.connectionState === 'connected') {\n this.dotEl.classList.add('tcw-connected');\n } else if (state.connectionState === 'error') {\n this.dotEl.classList.add('tcw-error');\n }\n\n this.messageEl.textContent = state.message;\n this.infoEl.textContent = `${state.symbol} ${state.timeframe}`;\n }\n\n destroy(): void {\n this.el.remove();\n }\n}\n","import type { ChartType, DrawingToolType, TimeFrame } from '@tradecanvas/commons';\n\nexport interface CommandItem {\n id: string;\n label: string;\n category: 'indicator' | 'chartType' | 'drawing' | 'timeframe' | 'action';\n shortcut?: string;\n active?: boolean;\n}\n\nexport interface CommandPaletteCallbacks {\n onIndicator: (id: string) => void;\n onChartType: (type: ChartType) => void;\n onDrawingTool: (tool: DrawingToolType) => void;\n onTimeframe: (tf: TimeFrame) => void;\n onAction: (id: string) => void;\n onClose: () => void;\n}\n\nexport class WidgetCommandPalette {\n private backdrop: HTMLDivElement | null = null;\n private modal: HTMLDivElement | null = null;\n private input: HTMLInputElement | null = null;\n private list: HTMLDivElement | null = null;\n private items: CommandItem[] = [];\n private filtered: CommandItem[] = [];\n private selectedIndex = 0;\n private callbacks: CommandPaletteCallbacks;\n private boundKeydown: (e: KeyboardEvent) => void;\n\n constructor(callbacks: CommandPaletteCallbacks) {\n this.callbacks = callbacks;\n this.boundKeydown = this.handleKeydown.bind(this);\n }\n\n open(items: CommandItem[]): void {\n if (this.backdrop) return;\n this.items = items;\n this.filtered = items;\n this.selectedIndex = 0;\n\n this.backdrop = document.createElement('div');\n this.backdrop.className = 'tcw-modal-backdrop';\n this.backdrop.addEventListener('click', () => this.close());\n\n this.modal = document.createElement('div');\n this.modal.className = 'tcw-cmd-palette';\n\n const header = document.createElement('div');\n header.className = 'tcw-cmd-header';\n\n const searchIcon = document.createElement('span');\n searchIcon.className = 'tcw-cmd-icon';\n searchIcon.textContent = '⌕';\n header.appendChild(searchIcon);\n\n this.input = document.createElement('input');\n this.input.className = 'tcw-cmd-input';\n this.input.type = 'text';\n this.input.placeholder = 'Search indicators, chart types, tools...';\n this.input.addEventListener('input', () => this.filter());\n header.appendChild(this.input);\n\n const hint = document.createElement('span');\n hint.className = 'tcw-cmd-hint';\n hint.textContent = 'ESC';\n header.appendChild(hint);\n\n this.modal.appendChild(header);\n\n this.list = document.createElement('div');\n this.list.className = 'tcw-cmd-list';\n this.modal.appendChild(this.list);\n\n const footer = document.createElement('div');\n footer.className = 'tcw-cmd-footer';\n footer.innerHTML = '<span>↑↓ Navigate</span><span>⏎ Select</span><span>Esc Close</span>';\n this.modal.appendChild(footer);\n\n document.body.appendChild(this.backdrop);\n document.body.appendChild(this.modal);\n\n this.renderList();\n this.input.focus();\n document.addEventListener('keydown', this.boundKeydown);\n }\n\n close(): void {\n document.removeEventListener('keydown', this.boundKeydown);\n this.backdrop?.remove();\n this.modal?.remove();\n this.backdrop = null;\n this.modal = null;\n this.input = null;\n this.list = null;\n this.callbacks.onClose();\n }\n\n isOpen(): boolean {\n return this.backdrop !== null;\n }\n\n private filter(): void {\n const query = this.input?.value.toLowerCase().trim() ?? '';\n if (!query) {\n this.filtered = this.items;\n } else {\n this.filtered = this.items.filter(item =>\n item.label.toLowerCase().includes(query) ||\n item.category.toLowerCase().includes(query) ||\n item.id.toLowerCase().includes(query),\n );\n }\n this.selectedIndex = 0;\n this.renderList();\n }\n\n private renderList(): void {\n if (!this.list) return;\n this.list.innerHTML = '';\n\n if (this.filtered.length === 0) {\n const empty = document.createElement('div');\n empty.className = 'tcw-cmd-empty';\n empty.textContent = 'No results found';\n this.list.appendChild(empty);\n return;\n }\n\n let currentCategory = '';\n for (let i = 0; i < this.filtered.length; i++) {\n const item = this.filtered[i];\n\n if (item.category !== currentCategory) {\n currentCategory = item.category;\n const label = document.createElement('div');\n label.className = 'tcw-cmd-category';\n label.textContent = this.categoryLabel(currentCategory);\n this.list.appendChild(label);\n }\n\n const row = document.createElement('button');\n row.className = 'tcw-cmd-item';\n if (i === this.selectedIndex) row.classList.add('tcw-selected');\n if (item.active) row.classList.add('tcw-active');\n row.dataset.index = String(i);\n\n const nameSpan = document.createElement('span');\n nameSpan.className = 'tcw-cmd-item-label';\n nameSpan.textContent = item.label;\n row.appendChild(nameSpan);\n\n if (item.active) {\n const check = document.createElement('span');\n check.className = 'tcw-cmd-check';\n check.textContent = '✓';\n row.appendChild(check);\n }\n\n if (item.shortcut) {\n const kbd = document.createElement('kbd');\n kbd.className = 'tcw-cmd-kbd';\n kbd.textContent = item.shortcut;\n row.appendChild(kbd);\n }\n\n row.addEventListener('click', () => this.select(i));\n row.addEventListener('mouseenter', () => {\n this.selectedIndex = i;\n this.updateSelection();\n });\n\n this.list.appendChild(row);\n }\n }\n\n private updateSelection(): void {\n if (!this.list) return;\n const items = this.list.querySelectorAll('.tcw-cmd-item');\n items.forEach((el, i) => {\n el.classList.toggle('tcw-selected', i === this.selectedIndex);\n });\n items[this.selectedIndex]?.scrollIntoView({ block: 'nearest' });\n }\n\n private select(index: number): void {\n const item = this.filtered[index];\n if (!item) return;\n\n switch (item.category) {\n case 'indicator':\n this.callbacks.onIndicator(item.id);\n break;\n case 'chartType':\n this.callbacks.onChartType(item.id as ChartType);\n break;\n case 'drawing':\n this.callbacks.onDrawingTool(item.id as DrawingToolType);\n break;\n case 'timeframe':\n this.callbacks.onTimeframe(item.id as TimeFrame);\n break;\n case 'action':\n this.callbacks.onAction(item.id);\n break;\n }\n this.close();\n }\n\n private handleKeydown(e: KeyboardEvent): void {\n switch (e.key) {\n case 'Escape':\n e.preventDefault();\n this.close();\n break;\n case 'ArrowDown':\n e.preventDefault();\n if (this.filtered.length > 0) {\n this.selectedIndex = (this.selectedIndex + 1) % this.filtered.length;\n this.updateSelection();\n }\n break;\n case 'ArrowUp':\n e.preventDefault();\n if (this.filtered.length > 0) {\n this.selectedIndex = (this.selectedIndex - 1 + this.filtered.length) % this.filtered.length;\n this.updateSelection();\n }\n break;\n case 'Enter':\n e.preventDefault();\n this.select(this.selectedIndex);\n break;\n }\n }\n\n private categoryLabel(cat: string): string {\n switch (cat) {\n case 'indicator': return 'Indicators';\n case 'chartType': return 'Chart Types';\n case 'drawing': return 'Drawing Tools';\n case 'timeframe': return 'Timeframes';\n case 'action': return 'Actions';\n default: return cat;\n }\n }\n\n destroy(): void {\n this.close();\n }\n}\n","/**\n * Lightweight fuzzy symbol picker. Reuses the command-palette CSS for visual\n * consistency. Scoring is a cheap subsequence match — good enough for symbol\n * lists in the low thousands without pulling in a fuzzy-search dependency.\n */\nexport interface SymbolSearchCallbacks {\n onPick: (symbol: string) => void;\n onClose: () => void;\n}\n\ninterface ScoredSymbol {\n symbol: string;\n score: number;\n}\n\nexport class WidgetSymbolSearch {\n private backdrop: HTMLDivElement | null = null;\n private modal: HTMLDivElement | null = null;\n private input: HTMLInputElement | null = null;\n private list: HTMLDivElement | null = null;\n private symbols: string[] = [];\n private current: string = '';\n private filtered: ScoredSymbol[] = [];\n private selectedIndex = 0;\n private callbacks: SymbolSearchCallbacks;\n private boundKeydown: (e: KeyboardEvent) => void;\n /** One-shot pick override — when set, this open() routes picks here instead. */\n private pickOverride: ((symbol: string) => void) | null = null;\n\n constructor(callbacks: SymbolSearchCallbacks) {\n this.callbacks = callbacks;\n this.boundKeydown = this.handleKeydown.bind(this);\n }\n\n open(symbols: string[], current: string, onPick?: (symbol: string) => void): void {\n if (this.backdrop) return;\n this.pickOverride = onPick ?? null;\n this.symbols = symbols;\n this.current = current;\n this.filtered = symbols.map(s => ({ symbol: s, score: 0 }));\n this.selectedIndex = Math.max(0, symbols.indexOf(current));\n\n this.backdrop = document.createElement('div');\n this.backdrop.className = 'tcw-modal-backdrop';\n this.backdrop.addEventListener('click', () => this.close());\n\n this.modal = document.createElement('div');\n this.modal.className = 'tcw-cmd-palette';\n\n const header = document.createElement('div');\n header.className = 'tcw-cmd-header';\n\n const icon = document.createElement('span');\n icon.className = 'tcw-cmd-icon';\n icon.innerHTML = svgSearch();\n header.appendChild(icon);\n\n this.input = document.createElement('input');\n this.input.className = 'tcw-cmd-input';\n this.input.type = 'text';\n this.input.placeholder = 'Search symbol… (e.g. BTC, ETH, AAPL)';\n this.input.autocomplete = 'off';\n this.input.spellcheck = false;\n this.input.addEventListener('input', () => this.filter());\n header.appendChild(this.input);\n\n const hint = document.createElement('span');\n hint.className = 'tcw-cmd-hint';\n hint.textContent = 'ESC';\n header.appendChild(hint);\n\n this.modal.appendChild(header);\n\n this.list = document.createElement('div');\n this.list.className = 'tcw-cmd-list';\n this.modal.appendChild(this.list);\n\n const footer = document.createElement('div');\n footer.className = 'tcw-cmd-footer';\n footer.innerHTML = '<span>↑↓ Navigate</span><span>⏎ Open</span><span>Esc Close</span>';\n this.modal.appendChild(footer);\n\n document.body.appendChild(this.backdrop);\n document.body.appendChild(this.modal);\n\n this.renderList();\n this.input.focus();\n document.addEventListener('keydown', this.boundKeydown);\n }\n\n close(): void {\n document.removeEventListener('keydown', this.boundKeydown);\n this.backdrop?.remove();\n this.modal?.remove();\n this.backdrop = null;\n this.modal = null;\n this.input = null;\n this.list = null;\n this.pickOverride = null;\n this.callbacks.onClose();\n }\n\n isOpen(): boolean {\n return this.backdrop !== null;\n }\n\n destroy(): void {\n this.close();\n }\n\n private filter(): void {\n const q = (this.input?.value ?? '').toUpperCase().trim();\n if (!q) {\n this.filtered = this.symbols.map(s => ({ symbol: s, score: 0 }));\n } else {\n this.filtered = this.symbols\n .map(s => ({ symbol: s, score: scoreMatch(s.toUpperCase(), q) }))\n .filter(r => r.score > 0)\n .sort((a, b) => b.score - a.score);\n }\n this.selectedIndex = 0;\n this.renderList();\n }\n\n private renderList(): void {\n if (!this.list) return;\n this.list.innerHTML = '';\n\n if (this.filtered.length === 0) {\n const empty = document.createElement('div');\n empty.className = 'tcw-cmd-empty';\n empty.textContent = 'No symbols match';\n this.list.appendChild(empty);\n return;\n }\n\n const query = (this.input?.value ?? '').toUpperCase().trim();\n for (let i = 0; i < this.filtered.length; i++) {\n const { symbol } = this.filtered[i];\n const row = document.createElement('button');\n row.className = 'tcw-cmd-item';\n if (i === this.selectedIndex) row.classList.add('tcw-selected');\n if (symbol === this.current) row.classList.add('tcw-active');\n\n const label = document.createElement('span');\n label.className = 'tcw-cmd-item-label';\n label.innerHTML = highlight(symbol, query);\n row.appendChild(label);\n\n if (symbol === this.current) {\n const check = document.createElement('span');\n check.className = 'tcw-cmd-check';\n check.textContent = '✓';\n row.appendChild(check);\n }\n\n row.addEventListener('click', () => this.pick(i));\n row.addEventListener('mouseenter', () => {\n this.selectedIndex = i;\n this.updateSelection();\n });\n\n this.list.appendChild(row);\n }\n }\n\n private updateSelection(): void {\n if (!this.list) return;\n const items = this.list.querySelectorAll('.tcw-cmd-item');\n items.forEach((el, i) => el.classList.toggle('tcw-selected', i === this.selectedIndex));\n items[this.selectedIndex]?.scrollIntoView({ block: 'nearest' });\n }\n\n private pick(index: number): void {\n const entry = this.filtered[index];\n if (!entry) return;\n const override = this.pickOverride;\n if (override) override(entry.symbol);\n else this.callbacks.onPick(entry.symbol);\n this.close();\n }\n\n private handleKeydown(e: KeyboardEvent): void {\n switch (e.key) {\n case 'Escape':\n e.preventDefault();\n this.close();\n break;\n case 'ArrowDown':\n e.preventDefault();\n if (this.filtered.length > 0) {\n this.selectedIndex = (this.selectedIndex + 1) % this.filtered.length;\n this.updateSelection();\n }\n break;\n case 'ArrowUp':\n e.preventDefault();\n if (this.filtered.length > 0) {\n this.selectedIndex = (this.selectedIndex - 1 + this.filtered.length) % this.filtered.length;\n this.updateSelection();\n }\n break;\n case 'Enter':\n e.preventDefault();\n this.pick(this.selectedIndex);\n break;\n }\n }\n}\n\n/**\n * Cheap fuzzy score:\n * exact match → 1000\n * starts-with → 500 + tighter-prefix bonus\n * subsequence match → 100 − gap penalty\n * no match → 0\n */\nfunction scoreMatch(symbol: string, query: string): number {\n if (symbol === query) return 1000;\n if (symbol.startsWith(query)) return 500 + (50 - Math.min(50, symbol.length - query.length));\n if (symbol.includes(query)) return 200 + (50 - Math.min(50, symbol.length - query.length));\n\n let qi = 0;\n let lastIdx = -1;\n let gapPenalty = 0;\n for (let i = 0; i < symbol.length && qi < query.length; i++) {\n if (symbol[i] === query[qi]) {\n if (lastIdx >= 0) gapPenalty += i - lastIdx - 1;\n lastIdx = i;\n qi++;\n }\n }\n if (qi < query.length) return 0;\n return 100 - Math.min(99, gapPenalty);\n}\n\nfunction highlight(symbol: string, query: string): string {\n if (!query) return escapeHtml(symbol);\n const upper = symbol.toUpperCase();\n let out = '';\n let qi = 0;\n for (let i = 0; i < symbol.length; i++) {\n if (qi < query.length && upper[i] === query[qi]) {\n out += `<mark style=\"background:transparent;color:var(--tcw-accent);font-weight:700\">${escapeHtml(symbol[i])}</mark>`;\n qi++;\n } else {\n out += escapeHtml(symbol[i]);\n }\n }\n return out;\n}\n\nfunction escapeHtml(s: string): string {\n return s.replace(/[&<>\"']/g, ch => ({\n '&': '&', '<': '<', '>': '>', '\"': '"', \"'\": ''',\n } as Record<string, string>)[ch]);\n}\n\nfunction svgSearch(): string {\n return '<svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"11\" cy=\"11\" r=\"7\"/><path d=\"m21 21-4.3-4.3\"/></svg>';\n}\n","/**\n * Keyboard-shortcut reference sheet. Bound to `?` (and `Shift+/`). Surfaces\n * shortcuts so users discover the widget's hidden interaction model — a\n * premium-feel detail TradingView, Linear, Figma, etc. all ship.\n */\nexport interface HotkeySheetCallbacks {\n onClose: () => void;\n}\n\ninterface HotkeyEntry {\n keys: string[];\n label: string;\n}\n\ninterface HotkeyGroup {\n title: string;\n entries: HotkeyEntry[];\n}\n\nconst isMac =\n typeof navigator !== 'undefined' && /mac|iphone|ipad|ipod/i.test(navigator.platform || navigator.userAgent);\nconst mod = isMac ? '⌘' : 'Ctrl';\n\nconst GROUPS: HotkeyGroup[] = [\n {\n title: 'Search & navigation',\n entries: [\n { keys: [mod, 'K'], label: 'Command palette' },\n { keys: [mod, 'P'], label: 'Symbol search' },\n { keys: ['?'], label: 'Show this sheet' },\n ],\n },\n {\n title: 'Chart manipulation',\n entries: [\n { keys: ['Shift', 'Drag'], label: 'Measure tool (bars × price Δ)' },\n { keys: ['Drag', 'Price axis'], label: 'Compress / expand vertical scale' },\n { keys: ['Drag', 'Time axis'], label: 'Zoom time axis' },\n { keys: ['Double-click', 'Price axis'], label: 'Re-enable auto-scale' },\n { keys: ['Double-click', 'Time axis'], label: 'Fit content' },\n { keys: ['Scroll'], label: 'Zoom around cursor' },\n ],\n },\n {\n title: 'Touch (mobile / tablet)',\n entries: [\n { keys: ['1 finger', 'Drag'], label: 'Pan / move crosshair' },\n { keys: ['2 fingers', 'Pinch'], label: 'Zoom around midpoint' },\n { keys: ['Long-press'], label: 'Pin OHLC tooltip at bar' },\n { keys: ['Drag', 'Axis strip'], label: 'Scale price / time axis' },\n ],\n },\n {\n title: 'Keyboard',\n entries: [\n { keys: ['←', '→'], label: 'Pan one bar' },\n { keys: ['+', '−'], label: 'Zoom in / out' },\n { keys: ['Home'], label: 'Scroll to start' },\n { keys: ['End'], label: 'Scroll to end (live edge)' },\n { keys: ['F'], label: 'Fit content' },\n ],\n },\n {\n title: 'Drawing',\n entries: [\n { keys: [mod, 'Z'], label: 'Undo' },\n { keys: [mod, 'Shift', 'Z'], label: 'Redo' },\n { keys: ['Esc'], label: 'Cancel active drawing' },\n ],\n },\n];\n\nexport class WidgetHotkeySheet {\n private backdrop: HTMLDivElement | null = null;\n private modal: HTMLDivElement | null = null;\n private callbacks: HotkeySheetCallbacks;\n private boundKeydown: (e: KeyboardEvent) => void;\n\n constructor(callbacks: HotkeySheetCallbacks) {\n this.callbacks = callbacks;\n this.boundKeydown = (e) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n this.close();\n }\n };\n }\n\n open(): void {\n if (this.backdrop) return;\n\n this.backdrop = document.createElement('div');\n this.backdrop.className = 'tcw-modal-backdrop';\n this.backdrop.addEventListener('click', () => this.close());\n\n this.modal = document.createElement('div');\n this.modal.className = 'tcw-modal tcw-hotkey-sheet';\n this.modal.style.width = '640px';\n\n const header = document.createElement('div');\n header.className = 'tcw-modal-header';\n header.innerHTML = '<h3>Keyboard shortcuts</h3>';\n const closeBtn = document.createElement('button');\n closeBtn.className = 'tcw-modal-close';\n closeBtn.setAttribute('aria-label', 'Close');\n closeBtn.innerHTML = '×';\n closeBtn.addEventListener('click', () => this.close());\n header.appendChild(closeBtn);\n this.modal.appendChild(header);\n\n const body = document.createElement('div');\n body.className = 'tcw-modal-body';\n\n const grid = document.createElement('div');\n grid.className = 'tcw-hotkey-grid';\n\n for (const group of GROUPS) {\n const section = document.createElement('section');\n section.className = 'tcw-hotkey-section';\n const title = document.createElement('div');\n title.className = 'tcw-settings-section-title';\n title.textContent = group.title;\n section.appendChild(title);\n\n for (const entry of group.entries) {\n const row = document.createElement('div');\n row.className = 'tcw-hotkey-row';\n\n const keys = document.createElement('div');\n keys.className = 'tcw-hotkey-keys';\n for (let i = 0; i < entry.keys.length; i++) {\n if (i > 0) {\n const plus = document.createElement('span');\n plus.className = 'tcw-hotkey-sep';\n plus.textContent = '+';\n keys.appendChild(plus);\n }\n const kbd = document.createElement('kbd');\n kbd.className = 'tcw-cmd-kbd';\n kbd.textContent = entry.keys[i];\n keys.appendChild(kbd);\n }\n row.appendChild(keys);\n\n const label = document.createElement('span');\n label.className = 'tcw-hotkey-label';\n label.textContent = entry.label;\n row.appendChild(label);\n\n section.appendChild(row);\n }\n\n grid.appendChild(section);\n }\n\n body.appendChild(grid);\n this.modal.appendChild(body);\n\n const footer = document.createElement('div');\n footer.className = 'tcw-modal-footer';\n footer.innerHTML = '<span style=\"font-size:11px;color:var(--tcw-text-muted)\">Press ? anytime to show this sheet</span>';\n const ok = document.createElement('button');\n ok.className = 'tcw-done-btn';\n ok.textContent = 'Got it';\n ok.addEventListener('click', () => this.close());\n footer.appendChild(ok);\n this.modal.appendChild(footer);\n\n document.body.appendChild(this.backdrop);\n document.body.appendChild(this.modal);\n\n document.addEventListener('keydown', this.boundKeydown);\n }\n\n close(): void {\n document.removeEventListener('keydown', this.boundKeydown);\n this.backdrop?.remove();\n this.modal?.remove();\n this.backdrop = null;\n this.modal = null;\n this.callbacks.onClose();\n }\n\n isOpen(): boolean {\n return this.backdrop !== null;\n }\n\n destroy(): void {\n this.close();\n }\n}\n","/**\r\n * Replay scrubber bar — surfaces the chart's existing replay engine as a\r\n * visible bottom-of-chart control. Mounts under the chart container, owns\r\n * its own lifecycle, and reports user intent up via callbacks (no chart\r\n * coupling — the host calls chart.replayStart() / replayPause() / etc.).\r\n */\r\nexport interface ReplayBarCallbacks {\r\n onPlay: () => void;\r\n onPause: () => void;\r\n onStop: () => void;\r\n onStepBack: () => void;\r\n onStepForward: () => void;\r\n onSeek: (index: number) => void;\r\n onSpeedChange: (barsPerSecond: number) => void;\r\n onClose: () => void;\r\n}\r\n\r\nexport type ReplayBarState = 'playing' | 'paused' | 'stopped';\r\n\r\nconst SPEEDS = [0.5, 1, 2, 5, 10, 20, 50, 100];\r\n\r\nexport class WidgetReplayBar {\r\n private root: HTMLDivElement | null = null;\r\n private scrubber: HTMLInputElement | null = null;\r\n private progressLabel: HTMLSpanElement | null = null;\r\n private playBtn: HTMLButtonElement | null = null;\r\n private state: ReplayBarState = 'stopped';\r\n private total = 0;\r\n private speed = 5;\r\n private callbacks: ReplayBarCallbacks;\r\n\r\n constructor(callbacks: ReplayBarCallbacks) {\r\n this.callbacks = callbacks;\r\n }\r\n\r\n mount(host: HTMLElement, opts: { total: number; speed?: number }): void {\r\n if (this.root) return;\r\n this.total = Math.max(0, opts.total);\r\n this.speed = opts.speed ?? 5;\r\n this.state = 'paused';\r\n\r\n this.root = document.createElement('div');\r\n this.root.className = 'tcw-replay-bar';\r\n this.root.innerHTML = this.markup();\r\n\r\n host.appendChild(this.root);\r\n this.wireEvents();\r\n this.syncUi();\r\n }\r\n\r\n unmount(): void {\r\n this.root?.remove();\r\n this.root = null;\r\n this.scrubber = null;\r\n this.progressLabel = null;\r\n this.playBtn = null;\r\n this.state = 'stopped';\r\n }\r\n\r\n isMounted(): boolean {\r\n return this.root !== null;\r\n }\r\n\r\n setState(state: ReplayBarState): void {\r\n this.state = state;\r\n this.syncUi();\r\n }\r\n\r\n setProgress(current: number, total: number): void {\r\n this.total = total;\r\n if (this.scrubber) {\r\n this.scrubber.max = String(Math.max(0, total - 1));\r\n this.scrubber.value = String(current);\r\n }\r\n if (this.progressLabel) {\r\n this.progressLabel.textContent = `${current + 1} / ${total}`;\r\n }\r\n }\r\n\r\n destroy(): void {\r\n this.unmount();\r\n }\r\n\r\n private markup(): string {\r\n const speeds = SPEEDS.map(s => `<option value=\"${s}\"${s === this.speed ? ' selected' : ''}>${s}× bars/s</option>`).join('');\r\n return `\r\n <button class=\"tcw-replay-btn\" data-act=\"close\" title=\"Exit replay\" aria-label=\"Exit replay\">${svgX()}</button>\r\n <button class=\"tcw-replay-btn\" data-act=\"stepBack\" title=\"Step back\" aria-label=\"Step back\">${svgStepBack()}</button>\r\n <button class=\"tcw-replay-btn tcw-replay-play\" data-act=\"play\" title=\"Play / pause\" aria-label=\"Play / pause\">${svgPlay()}</button>\r\n <button class=\"tcw-replay-btn\" data-act=\"stepForward\" title=\"Step forward\" aria-label=\"Step forward\">${svgStepForward()}</button>\r\n <input type=\"range\" class=\"tcw-replay-scrubber\" data-act=\"seek\" min=\"0\" max=\"${Math.max(0, this.total - 1)}\" value=\"0\" step=\"1\" />\r\n <span class=\"tcw-replay-progress\" data-tcw=\"progress\">1 / ${this.total}</span>\r\n <select class=\"tcw-replay-speed\" data-act=\"speed\">${speeds}</select>\r\n `;\r\n }\r\n\r\n private wireEvents(): void {\r\n if (!this.root) return;\r\n this.scrubber = this.root.querySelector('input[data-act=\"seek\"]');\r\n this.progressLabel = this.root.querySelector('[data-tcw=\"progress\"]');\r\n this.playBtn = this.root.querySelector('button[data-act=\"play\"]');\r\n\r\n this.root.querySelector('[data-act=\"close\"]')?.addEventListener('click', () => this.callbacks.onClose());\r\n this.root.querySelector('[data-act=\"stepBack\"]')?.addEventListener('click', () => this.callbacks.onStepBack());\r\n this.root.querySelector('[data-act=\"stepForward\"]')?.addEventListener('click', () => this.callbacks.onStepForward());\r\n this.playBtn?.addEventListener('click', () => {\r\n if (this.state === 'playing') {\r\n this.callbacks.onPause();\r\n } else {\r\n this.callbacks.onPlay();\r\n }\r\n });\r\n this.scrubber?.addEventListener('input', () => {\r\n const idx = Number(this.scrubber!.value);\r\n this.callbacks.onSeek(idx);\r\n });\r\n (this.root.querySelector('[data-act=\"speed\"]') as HTMLSelectElement | null)?.addEventListener('change', (e) => {\r\n const v = Number((e.target as HTMLSelectElement).value);\r\n this.speed = v;\r\n this.callbacks.onSpeedChange(v);\r\n });\r\n }\r\n\r\n private syncUi(): void {\r\n if (!this.playBtn) return;\r\n this.playBtn.innerHTML = this.state === 'playing' ? svgPause() : svgPlay();\r\n this.playBtn.title = this.state === 'playing' ? 'Pause' : 'Play';\r\n }\r\n}\r\n\r\nfunction svgPlay(): string {\r\n return '<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M8 5v14l11-7L8 5z\"/></svg>';\r\n}\r\nfunction svgPause(): string {\r\n return '<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M6 5h4v14H6zM14 5h4v14h-4z\"/></svg>';\r\n}\r\nfunction svgStepBack(): string {\r\n return '<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M6 6h2v12H6zM20 6L9 12l11 6V6z\"/></svg>';\r\n}\r\nfunction svgStepForward(): string {\r\n return '<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"currentColor\"><path d=\"M4 6l11 6L4 18V6zM16 6h2v12h-2z\"/></svg>';\r\n}\r\nfunction svgX(): string {\r\n return '<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2.2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><path d=\"M18 6L6 18M6 6l12 12\"/></svg>';\r\n}\r\n","/**\n * Watchlist sidebar — vertical list of symbols, each with last price, %\n * change, and a mini sparkline. Clicking switches the chart's symbol.\n *\n * The widget tracks the *active* symbol's price/spark automatically from the\n * live stream. For non-active symbols, the host can push data via\n * `setEntry(symbol, …)` so the row reflects whatever the app already has.\n */\nexport interface WatchlistEntry {\n symbol: string;\n lastPrice?: number;\n /** Reference price for % calc (usually session open or 24h-ago close). */\n refPrice?: number;\n /** Recent close samples for the sparkline — last point is the live price. */\n sparkline?: number[];\n}\n\nexport interface WatchlistCallbacks {\n onSelect: (symbol: string) => void;\n}\n\nexport class WidgetWatchlist {\n private el: HTMLDivElement;\n private listEl: HTMLDivElement;\n private rowMap = new Map<string, {\n row: HTMLDivElement;\n priceEl: HTMLSpanElement;\n changeEl: HTMLSpanElement;\n sparkCanvas: HTMLCanvasElement;\n }>();\n private entries = new Map<string, WatchlistEntry>();\n private active: string | null = null;\n private callbacks: WatchlistCallbacks;\n\n constructor(host: HTMLElement, symbols: string[], callbacks: WatchlistCallbacks) {\n this.callbacks = callbacks;\n\n this.el = document.createElement('div');\n this.el.className = 'tcw-watchlist';\n\n const header = document.createElement('div');\n header.className = 'tcw-watchlist-header';\n header.textContent = 'Watchlist';\n this.el.appendChild(header);\n\n this.listEl = document.createElement('div');\n this.listEl.className = 'tcw-watchlist-list';\n this.el.appendChild(this.listEl);\n\n for (const symbol of symbols) {\n this.entries.set(symbol, { symbol });\n this.appendRow(symbol);\n }\n\n host.appendChild(this.el);\n }\n\n /** Replace the symbol set. Rows are diff'd so DOM churn is minimal. */\n setSymbols(symbols: string[]): void {\n const next = new Set(symbols);\n for (const sym of this.rowMap.keys()) {\n if (!next.has(sym)) this.removeRow(sym);\n }\n for (const sym of symbols) {\n if (!this.rowMap.has(sym)) {\n this.entries.set(sym, this.entries.get(sym) ?? { symbol: sym });\n this.appendRow(sym);\n }\n }\n }\n\n setActive(symbol: string): void {\n if (this.active === symbol) return;\n if (this.active && this.rowMap.has(this.active)) {\n this.rowMap.get(this.active)!.row.classList.remove('tcw-watchlist-active');\n }\n this.active = symbol;\n const cur = this.rowMap.get(symbol);\n if (cur) cur.row.classList.add('tcw-watchlist-active');\n }\n\n /** Push a price tick into a row. The widget calls this automatically for\n * the active symbol. Apps can call it for the rest. */\n setEntry(symbol: string, patch: Partial<WatchlistEntry>): void {\n const prev = this.entries.get(symbol) ?? { symbol };\n const next = { ...prev, ...patch };\n this.entries.set(symbol, next);\n this.renderRow(symbol);\n }\n\n destroy(): void {\n this.el.remove();\n this.rowMap.clear();\n this.entries.clear();\n }\n\n private appendRow(symbol: string): void {\n const row = document.createElement('div');\n row.className = 'tcw-watchlist-row';\n row.tabIndex = 0;\n\n const label = document.createElement('div');\n label.className = 'tcw-watchlist-symbol';\n label.textContent = formatSymbol(symbol);\n\n const spark = document.createElement('canvas');\n spark.className = 'tcw-watchlist-spark';\n spark.width = 64;\n spark.height = 22;\n\n const right = document.createElement('div');\n right.className = 'tcw-watchlist-stats';\n const priceEl = document.createElement('span');\n priceEl.className = 'tcw-watchlist-price';\n priceEl.textContent = '—';\n const changeEl = document.createElement('span');\n changeEl.className = 'tcw-watchlist-change';\n changeEl.textContent = '';\n right.appendChild(priceEl);\n right.appendChild(changeEl);\n\n row.appendChild(label);\n row.appendChild(spark);\n row.appendChild(right);\n\n row.addEventListener('click', () => this.callbacks.onSelect(symbol));\n row.addEventListener('keydown', (e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n this.callbacks.onSelect(symbol);\n }\n });\n\n this.listEl.appendChild(row);\n this.rowMap.set(symbol, { row, priceEl, changeEl, sparkCanvas: spark });\n if (symbol === this.active) row.classList.add('tcw-watchlist-active');\n }\n\n private removeRow(symbol: string): void {\n const ref = this.rowMap.get(symbol);\n if (!ref) return;\n ref.row.remove();\n this.rowMap.delete(symbol);\n }\n\n private renderRow(symbol: string): void {\n const ref = this.rowMap.get(symbol);\n const entry = this.entries.get(symbol);\n if (!ref || !entry) return;\n\n if (entry.lastPrice !== undefined) {\n ref.priceEl.textContent = formatPrice(entry.lastPrice);\n }\n\n if (entry.lastPrice !== undefined && entry.refPrice !== undefined && entry.refPrice !== 0) {\n const diff = entry.lastPrice - entry.refPrice;\n const pct = (diff / entry.refPrice) * 100;\n const sign = diff >= 0 ? '+' : '';\n ref.changeEl.textContent = `${sign}${pct.toFixed(2)}%`;\n ref.changeEl.className = `tcw-watchlist-change ${diff >= 0 ? 'tcw-up' : 'tcw-down'}`;\n } else {\n ref.changeEl.textContent = '';\n }\n\n if (entry.sparkline && entry.sparkline.length >= 2) {\n drawSparkline(ref.sparkCanvas, entry.sparkline, entry.refPrice ?? entry.sparkline[0]);\n }\n }\n}\n\nfunction formatSymbol(symbol: string): string {\n // Add a / separator for typical crypto pair suffixes; leaves stock tickers\n // (AAPL, NVDA) alone.\n for (const quote of ['USDT', 'USD', 'BTC', 'ETH', 'EUR']) {\n if (symbol.length > quote.length && symbol.endsWith(quote)) {\n return symbol.slice(0, -quote.length) + '/' + quote;\n }\n }\n return symbol;\n}\n\nfunction formatPrice(v: number): string {\n if (v === 0) return '0';\n const abs = Math.abs(v);\n if (abs >= 1000) return v.toFixed(2);\n if (abs >= 1) return v.toFixed(4);\n return v.toPrecision(4);\n}\n\nfunction drawSparkline(canvas: HTMLCanvasElement, samples: number[], ref: number): void {\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n const dpr = window.devicePixelRatio || 1;\n if (canvas.width !== canvas.clientWidth * dpr) {\n canvas.width = (canvas.clientWidth || 64) * dpr;\n canvas.height = (canvas.clientHeight || 22) * dpr;\n }\n const w = canvas.width;\n const h = canvas.height;\n\n let lo = Infinity, hi = -Infinity;\n for (const v of samples) {\n if (v < lo) lo = v;\n if (v > hi) hi = v;\n }\n const span = Math.max(hi - lo, 1e-9);\n const last = samples[samples.length - 1];\n const up = last >= ref;\n const color = up ? '#26a17b' : '#f23645';\n\n ctx.clearRect(0, 0, w, h);\n ctx.lineWidth = 1.4 * dpr;\n ctx.strokeStyle = color;\n ctx.beginPath();\n const step = w / (samples.length - 1);\n for (let i = 0; i < samples.length; i++) {\n const x = i * step;\n const y = h - ((samples[i] - lo) / span) * (h - 4) - 2;\n if (i === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y);\n }\n ctx.stroke();\n}\n","import type { AlertCondition } from '@tradecanvas/core';\nimport { createIcon } from './icons.js';\n\nexport interface AlertListItem {\n id: string;\n price: number;\n condition: string;\n message?: string;\n triggered: boolean;\n channel?: string;\n label?: string;\n}\n\nexport interface AlertSource {\n /** `'price'` or `<instanceId>:<key>`. */\n channel: string;\n label: string;\n}\n\nexport interface AlertsPanelCallbacks {\n onAdd: (price: number, condition: AlertCondition, message: string | undefined, channel: string, label: string) => void;\n onRemove: (id: string) => void;\n onClear: () => void;\n /** Latest value for a source channel, used to prefill the add form. */\n getChannelValue: (channel: string) => number | null;\n formatPrice: (price: number) => string;\n}\n\nconst CONDITION_OPTIONS: { value: AlertCondition; label: string }[] = [\n { value: 'crossing', label: 'Crossing' },\n { value: 'crossingUp', label: 'Crossing up' },\n { value: 'crossingDown', label: 'Crossing down' },\n { value: 'greaterThan', label: 'Greater than' },\n { value: 'lessThan', label: 'Less than' },\n];\n\nconst CONDITION_LABEL = new Map(CONDITION_OPTIONS.map((o) => [o.value, o.label]));\n\nfunction roundForInput(v: number): number {\n return Math.round(v * 1e6) / 1e6;\n}\n\nfunction formatPlain(v: number): string {\n const abs = Math.abs(v);\n return abs >= 1000 ? v.toFixed(2) : abs >= 1 ? v.toFixed(2) : v.toPrecision(4);\n}\n\n/**\n * Floating price-alerts panel. Lists current alerts (with condition, price,\n * message, and a delete control) and an inline form to add a new one prefilled\n * with the current price. Toggled from the toolbar bell button; the host wires\n * add/remove back to the chart's `AlertManager`.\n */\nexport class WidgetAlertsPanel {\n private el: HTMLDivElement;\n private listEl: HTMLDivElement;\n private priceInput: HTMLInputElement;\n private conditionSelect: HTMLSelectElement;\n private sourceSelect: HTMLSelectElement;\n private messageInput: HTMLInputElement;\n private emptyEl: HTMLDivElement;\n private callbacks: AlertsPanelCallbacks;\n private open = false;\n private alerts: AlertListItem[] = [];\n private sources: AlertSource[] = [{ channel: 'price', label: 'Price' }];\n\n constructor(host: HTMLElement, callbacks: AlertsPanelCallbacks) {\n this.callbacks = callbacks;\n\n this.el = document.createElement('div');\n this.el.className = 'tcw-alerts-panel';\n this.el.hidden = true;\n\n // Header\n const header = document.createElement('div');\n header.className = 'tcw-alerts-header';\n const title = document.createElement('span');\n title.textContent = 'Price Alerts';\n const closeBtn = document.createElement('button');\n closeBtn.className = 'tcw-alerts-close';\n closeBtn.type = 'button';\n closeBtn.setAttribute('aria-label', 'Close alerts');\n closeBtn.innerHTML = createIcon('x', 14);\n closeBtn.addEventListener('click', () => this.close());\n header.appendChild(title);\n header.appendChild(closeBtn);\n this.el.appendChild(header);\n\n // Add form\n const form = document.createElement('form');\n form.className = 'tcw-alerts-form';\n\n this.sourceSelect = document.createElement('select');\n this.sourceSelect.className = 'tcw-alerts-source';\n this.sourceSelect.addEventListener('change', () => this.prefillPrice());\n\n this.priceInput = document.createElement('input');\n this.priceInput.type = 'number';\n this.priceInput.step = 'any';\n this.priceInput.placeholder = 'Value';\n this.priceInput.className = 'tcw-alerts-price';\n this.priceInput.required = true;\n\n this.conditionSelect = document.createElement('select');\n this.conditionSelect.className = 'tcw-alerts-condition';\n for (const opt of CONDITION_OPTIONS) {\n const o = document.createElement('option');\n o.value = opt.value;\n o.textContent = opt.label;\n this.conditionSelect.appendChild(o);\n }\n\n this.messageInput = document.createElement('input');\n this.messageInput.type = 'text';\n this.messageInput.placeholder = 'Note (optional)';\n this.messageInput.className = 'tcw-alerts-message';\n\n const addBtn = document.createElement('button');\n addBtn.type = 'submit';\n addBtn.className = 'tcw-alerts-add';\n addBtn.innerHTML = `${createIcon('plus', 14)}<span>Add alert</span>`;\n\n form.appendChild(this.sourceSelect);\n form.appendChild(this.priceInput);\n form.appendChild(this.conditionSelect);\n form.appendChild(this.messageInput);\n form.appendChild(addBtn);\n form.addEventListener('submit', (e) => {\n e.preventDefault();\n this.submitForm();\n });\n this.el.appendChild(form);\n\n // List\n this.listEl = document.createElement('div');\n this.listEl.className = 'tcw-alerts-list';\n this.el.appendChild(this.listEl);\n\n this.emptyEl = document.createElement('div');\n this.emptyEl.className = 'tcw-alerts-empty';\n this.emptyEl.textContent = 'No alerts yet. Add one above, or right-click the chart.';\n this.listEl.appendChild(this.emptyEl);\n\n this.renderSources();\n host.appendChild(this.el);\n }\n\n /** Replace the alert-source options (price + indicator lines). */\n setSources(sources: AlertSource[]): void {\n this.sources = sources.length > 0 ? sources : [{ channel: 'price', label: 'Price' }];\n this.renderSources();\n }\n\n private renderSources(): void {\n const current = this.sourceSelect.value || 'price';\n this.sourceSelect.replaceChildren();\n for (const src of this.sources) {\n const o = document.createElement('option');\n o.value = src.channel;\n o.textContent = src.label;\n this.sourceSelect.appendChild(o);\n }\n // Keep the prior selection if it still exists, else default to price.\n this.sourceSelect.value = this.sources.some((s) => s.channel === current) ? current : 'price';\n }\n\n isOpen(): boolean {\n return this.open;\n }\n\n toggle(): void {\n this.open ? this.close() : this.openPanel();\n }\n\n openPanel(): void {\n this.open = true;\n this.el.hidden = false;\n if (this.priceInput.value === '') this.prefillPrice();\n }\n\n /** Fill the value input with the selected source's current value. */\n private prefillPrice(): void {\n const v = this.callbacks.getChannelValue(this.sourceSelect.value || 'price');\n this.priceInput.value = v !== null ? String(roundForInput(v)) : '';\n }\n\n close(): void {\n this.open = false;\n this.el.hidden = true;\n }\n\n /** Replace the displayed alert list. */\n setAlerts(alerts: AlertListItem[]): void {\n this.alerts = alerts;\n this.renderList();\n }\n\n destroy(): void {\n this.el.remove();\n }\n\n private submitForm(): void {\n const price = Number(this.priceInput.value);\n if (!Number.isFinite(price)) return;\n const condition = this.conditionSelect.value as AlertCondition;\n const message = this.messageInput.value.trim() || undefined;\n const channel = this.sourceSelect.value || 'price';\n const label = this.sources.find((s) => s.channel === channel)?.label ?? 'Price';\n this.callbacks.onAdd(price, condition, message, channel, label);\n this.messageInput.value = '';\n this.prefillPrice();\n }\n\n private renderList(): void {\n // Clear rows but keep the empty placeholder reference.\n this.listEl.replaceChildren();\n\n if (this.alerts.length === 0) {\n this.listEl.appendChild(this.emptyEl);\n return;\n }\n\n // Show most recent first.\n for (const alert of [...this.alerts].reverse()) {\n const row = document.createElement('div');\n row.className = 'tcw-alerts-row' + (alert.triggered ? ' tcw-alerts-triggered' : '');\n\n const info = document.createElement('div');\n info.className = 'tcw-alerts-info';\n const main = document.createElement('div');\n main.className = 'tcw-alerts-row-main';\n const label = CONDITION_LABEL.get(alert.condition as AlertCondition) ?? alert.condition;\n const isIndicator = alert.channel && alert.channel !== 'price';\n const valueStr = isIndicator ? formatPlain(alert.price) : this.callbacks.formatPrice(alert.price);\n const prefix = isIndicator && alert.label ? `${alert.label} ` : '';\n main.textContent = `${prefix}${label} ${valueStr}`;\n info.appendChild(main);\n if (alert.message) {\n const note = document.createElement('div');\n note.className = 'tcw-alerts-row-note';\n note.textContent = alert.message;\n info.appendChild(note);\n }\n if (alert.triggered) {\n const badge = document.createElement('span');\n badge.className = 'tcw-alerts-badge';\n badge.textContent = 'triggered';\n main.appendChild(badge);\n }\n\n const del = document.createElement('button');\n del.type = 'button';\n del.className = 'tcw-alerts-del';\n del.setAttribute('aria-label', 'Delete alert');\n del.innerHTML = createIcon('trash', 14);\n del.addEventListener('click', () => this.callbacks.onRemove(alert.id));\n\n row.appendChild(info);\n row.appendChild(del);\n this.listEl.appendChild(row);\n }\n }\n}\n","import { createIcon } from './icons.js';\n\nexport interface ObjectTreeIndicator {\n instanceId: string;\n name: string;\n visible: boolean;\n}\n\nexport interface ObjectTreeDrawing {\n id: string;\n label: string;\n visible: boolean;\n locked: boolean;\n}\n\nexport interface ObjectTreeCompare {\n id: string;\n label: string;\n color: string;\n}\n\nexport interface ObjectTreeCallbacks {\n onRemoveIndicator: (instanceId: string) => void;\n onConfigureIndicator?: (instanceId: string) => void;\n onToggleIndicatorVisible?: (instanceId: string, visible: boolean) => void;\n onRemoveDrawing: (id: string) => void;\n onToggleDrawingVisible: (id: string, visible: boolean) => void;\n onToggleDrawingLocked: (id: string, locked: boolean) => void;\n /** When provided, a Compare section with an \"add\" button is shown. */\n onAddCompare?: () => void;\n onRemoveCompare?: (id: string) => void;\n}\n\n/**\n * Object-tree panel — TradingView's layers manager. Lists every active\n * indicator and drawing on the chart with per-item controls: indicators can be\n * removed; drawings can be shown/hidden, locked/unlocked, and removed. Toggled\n * from the toolbar layers button; the host wires actions back to the chart.\n */\nexport class WidgetObjectTree {\n private el: HTMLDivElement;\n private indicatorsEl: HTMLDivElement;\n private drawingsEl: HTMLDivElement;\n private compareEl: HTMLDivElement | null = null;\n private callbacks: ObjectTreeCallbacks;\n private open = false;\n\n constructor(host: HTMLElement, callbacks: ObjectTreeCallbacks) {\n this.callbacks = callbacks;\n\n this.el = document.createElement('div');\n this.el.className = 'tcw-tree-panel';\n this.el.hidden = true;\n\n const header = document.createElement('div');\n header.className = 'tcw-tree-header';\n const title = document.createElement('span');\n title.textContent = 'Objects';\n const closeBtn = document.createElement('button');\n closeBtn.type = 'button';\n closeBtn.className = 'tcw-tree-close';\n closeBtn.setAttribute('aria-label', 'Close objects');\n closeBtn.innerHTML = createIcon('x', 14);\n closeBtn.addEventListener('click', () => this.close());\n header.appendChild(title);\n header.appendChild(closeBtn);\n this.el.appendChild(header);\n\n this.indicatorsEl = this.makeSection('Indicators');\n this.drawingsEl = this.makeSection('Drawings');\n if (this.callbacks.onAddCompare) {\n this.compareEl = this.makeSection('Compare', () => this.callbacks.onAddCompare?.());\n }\n\n host.appendChild(this.el);\n }\n\n isOpen(): boolean {\n return this.open;\n }\n\n toggle(): void {\n this.open ? this.close() : this.openPanel();\n }\n\n openPanel(): void {\n this.open = true;\n this.el.hidden = false;\n }\n\n close(): void {\n this.open = false;\n this.el.hidden = true;\n }\n\n destroy(): void {\n this.el.remove();\n }\n\n /** Replace all lists. Cheap full re-render — counts are small. */\n setObjects(\n indicators: ObjectTreeIndicator[],\n drawings: ObjectTreeDrawing[],\n compares: ObjectTreeCompare[] = [],\n ): void {\n this.renderIndicators(indicators);\n this.renderDrawings(drawings);\n this.renderCompares(compares);\n }\n\n private makeSection(title: string, onAdd?: () => void): HTMLDivElement {\n const wrap = document.createElement('div');\n wrap.className = 'tcw-tree-section';\n const head = document.createElement('div');\n head.className = 'tcw-tree-section-head';\n const label = document.createElement('span');\n label.textContent = title;\n head.appendChild(label);\n if (onAdd) {\n const addBtn = document.createElement('button');\n addBtn.type = 'button';\n addBtn.className = 'tcw-tree-add';\n addBtn.setAttribute('aria-label', `Add ${title.toLowerCase()}`);\n addBtn.title = `Add ${title.toLowerCase()}`;\n addBtn.innerHTML = createIcon('plus', 13);\n addBtn.addEventListener('click', onAdd);\n head.appendChild(addBtn);\n }\n const list = document.createElement('div');\n list.className = 'tcw-tree-list';\n wrap.appendChild(head);\n wrap.appendChild(list);\n this.el.appendChild(wrap);\n return list;\n }\n\n private renderIndicators(indicators: ObjectTreeIndicator[]): void {\n this.indicatorsEl.replaceChildren();\n if (indicators.length === 0) {\n this.indicatorsEl.appendChild(this.emptyRow('No indicators'));\n return;\n }\n for (const ind of indicators) {\n const row = this.row(ind.name);\n if (!ind.visible) row.classList.add('tcw-tree-hidden');\n const actions = document.createElement('div');\n actions.className = 'tcw-tree-actions';\n if (this.callbacks.onToggleIndicatorVisible) {\n actions.appendChild(this.iconButton(\n ind.visible ? 'eye' : 'eyeOff',\n ind.visible ? 'Hide' : 'Show',\n '',\n () => this.callbacks.onToggleIndicatorVisible?.(ind.instanceId, !ind.visible),\n ));\n }\n if (this.callbacks.onConfigureIndicator) {\n actions.appendChild(this.iconButton('settings', 'Indicator settings', '', () =>\n this.callbacks.onConfigureIndicator?.(ind.instanceId),\n ));\n }\n actions.appendChild(this.iconButton('trash', 'Remove indicator', 'tcw-tree-del', () =>\n this.callbacks.onRemoveIndicator(ind.instanceId),\n ));\n row.appendChild(actions);\n this.indicatorsEl.appendChild(row);\n }\n }\n\n private renderDrawings(drawings: ObjectTreeDrawing[]): void {\n this.drawingsEl.replaceChildren();\n if (drawings.length === 0) {\n this.drawingsEl.appendChild(this.emptyRow('No drawings'));\n return;\n }\n for (const d of drawings) {\n const row = this.row(d.label);\n if (!d.visible) row.classList.add('tcw-tree-hidden');\n\n const actions = document.createElement('div');\n actions.className = 'tcw-tree-actions';\n actions.appendChild(this.iconButton(\n d.visible ? 'eye' : 'eyeOff',\n d.visible ? 'Hide' : 'Show',\n '',\n () => this.callbacks.onToggleDrawingVisible(d.id, !d.visible),\n ));\n actions.appendChild(this.iconButton(\n d.locked ? 'lock' : 'unlock',\n d.locked ? 'Unlock' : 'Lock',\n d.locked ? 'tcw-tree-on' : '',\n () => this.callbacks.onToggleDrawingLocked(d.id, !d.locked),\n ));\n actions.appendChild(this.iconButton('trash', 'Remove drawing', 'tcw-tree-del', () =>\n this.callbacks.onRemoveDrawing(d.id),\n ));\n row.appendChild(actions);\n this.drawingsEl.appendChild(row);\n }\n }\n\n private renderCompares(compares: ObjectTreeCompare[]): void {\n if (!this.compareEl) return;\n this.compareEl.replaceChildren();\n if (compares.length === 0) {\n this.compareEl.appendChild(this.emptyRow('No comparisons'));\n return;\n }\n for (const c of compares) {\n const row = this.row(c.label);\n const dot = document.createElement('span');\n dot.className = 'tcw-tree-dot';\n dot.style.background = c.color;\n row.insertBefore(dot, row.firstChild);\n if (this.callbacks.onRemoveCompare) {\n row.appendChild(this.iconButton('trash', 'Remove comparison', 'tcw-tree-del', () =>\n this.callbacks.onRemoveCompare?.(c.id),\n ));\n }\n this.compareEl.appendChild(row);\n }\n }\n\n private row(label: string): HTMLDivElement {\n const row = document.createElement('div');\n row.className = 'tcw-tree-row';\n const name = document.createElement('span');\n name.className = 'tcw-tree-name';\n name.textContent = label;\n name.title = label;\n row.appendChild(name);\n return row;\n }\n\n private emptyRow(text: string): HTMLDivElement {\n const el = document.createElement('div');\n el.className = 'tcw-tree-empty';\n el.textContent = text;\n return el;\n }\n\n private iconButton(icon: string, label: string, extraClass: string, onClick: () => void): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = `tcw-tree-btn ${extraClass}`.trim();\n btn.setAttribute('aria-label', label);\n btn.title = label;\n btn.innerHTML = createIcon(icon, 14);\n btn.addEventListener('click', onClick);\n return btn;\n }\n}\n\nconst DRAWING_TYPE_LABELS: Record<string, string> = {\n trendLine: 'Trend Line',\n ray: 'Ray',\n extendedLine: 'Extended Line',\n horizontalLine: 'Horizontal Line',\n verticalLine: 'Vertical Line',\n rectangle: 'Rectangle',\n ellipse: 'Ellipse',\n triangle: 'Triangle',\n arrow: 'Arrow',\n parallelChannel: 'Parallel Channel',\n regressionChannel: 'Regression Channel',\n pitchfork: 'Pitchfork',\n fibRetracement: 'Fib Retracement',\n fibExtension: 'Fib Extension',\n fibTimeZones: 'Fib Time Zones',\n gannBox: 'Gann Box',\n gannFan: 'Gann Fan',\n elliottWave: 'Elliott Wave',\n priceRange: 'Price Range',\n dateRange: 'Date Range',\n measure: 'Measure',\n textAnnotation: 'Text',\n anchoredVWAP: 'Anchored VWAP',\n volumeProfileRange: 'Volume Profile',\n};\n\n/** Human-readable label for a drawing type, falling back to the raw key. */\nexport function drawingTypeLabel(type: string): string {\n return DRAWING_TYPE_LABELS[type] ?? type;\n}\n","import { createIcon } from './icons.js';\n\nexport type IndicatorParamValue = number | string | boolean;\n\nexport interface IndicatorSettingsTarget {\n instanceId: string;\n name: string;\n /** Default config — defines the editable keys and their types. */\n defaults: Record<string, unknown>;\n /** Current values, overlaid on defaults. */\n params: Record<string, unknown>;\n}\n\nexport interface IndicatorSettingsCallbacks {\n onApply: (instanceId: string, params: Record<string, IndicatorParamValue>) => void;\n onClose: () => void;\n}\n\nconst HEX_RE = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;\n\nfunction titleCase(key: string): string {\n // camelCase / snake_case → \"Title Case\"\n return key\n .replace(/_/g, ' ')\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .replace(/^./, (c) => c.toUpperCase());\n}\n\n/**\n * Per-indicator parameter editor. Introspects the indicator's default config to\n * decide each control (number → stepper, boolean → toggle, hex string → color,\n * other string → text) and applies edits live via `onApply`.\n */\nexport class WidgetIndicatorSettings {\n private backdrop: HTMLDivElement;\n private modal: HTMLDivElement;\n private bodyEl: HTMLDivElement;\n private titleEl: HTMLHeadingElement;\n private callbacks: IndicatorSettingsCallbacks;\n private target: IndicatorSettingsTarget | null = null;\n private draft: Record<string, IndicatorParamValue> = {};\n\n constructor(host: HTMLElement, callbacks: IndicatorSettingsCallbacks) {\n this.callbacks = callbacks;\n\n this.backdrop = document.createElement('div');\n this.backdrop.className = 'tcw-modal-backdrop';\n this.backdrop.hidden = true;\n this.backdrop.addEventListener('click', (e) => {\n if (e.target === this.backdrop) this.close();\n });\n\n this.modal = document.createElement('div');\n this.modal.className = 'tcw-modal tcw-modal-narrow';\n\n const header = document.createElement('div');\n header.className = 'tcw-modal-header';\n this.titleEl = document.createElement('h3');\n this.titleEl.textContent = 'Indicator';\n const closeBtn = document.createElement('button');\n closeBtn.className = 'tcw-modal-close';\n closeBtn.setAttribute('aria-label', 'Close');\n closeBtn.innerHTML = createIcon('x', 16);\n closeBtn.addEventListener('click', () => this.close());\n header.appendChild(this.titleEl);\n header.appendChild(closeBtn);\n\n this.bodyEl = document.createElement('div');\n this.bodyEl.className = 'tcw-modal-body';\n\n const footer = document.createElement('div');\n footer.className = 'tcw-modal-footer';\n const resetBtn = document.createElement('button');\n resetBtn.className = 'tcw-reset-link';\n resetBtn.textContent = 'Reset to defaults';\n resetBtn.addEventListener('click', () => this.resetDefaults());\n const doneBtn = document.createElement('button');\n doneBtn.className = 'tcw-done-btn';\n doneBtn.textContent = 'Done';\n doneBtn.addEventListener('click', () => this.close());\n footer.appendChild(resetBtn);\n footer.appendChild(doneBtn);\n\n this.modal.appendChild(header);\n this.modal.appendChild(this.bodyEl);\n this.modal.appendChild(footer);\n this.backdrop.appendChild(this.modal);\n host.appendChild(this.backdrop);\n }\n\n open(target: IndicatorSettingsTarget): void {\n this.target = target;\n this.titleEl.textContent = `${target.name} settings`;\n this.draft = {};\n this.renderFields();\n this.backdrop.hidden = false;\n }\n\n close(): void {\n this.backdrop.hidden = true;\n this.target = null;\n this.callbacks.onClose();\n }\n\n isOpen(): boolean {\n return !this.backdrop.hidden;\n }\n\n destroy(): void {\n this.backdrop.remove();\n }\n\n private currentValue(key: string): IndicatorParamValue {\n if (key in this.draft) return this.draft[key];\n const cur = this.target?.params[key];\n const def = this.target?.defaults[key];\n const val = cur ?? def;\n return val as IndicatorParamValue;\n }\n\n private setValue(key: string, value: IndicatorParamValue): void {\n if (!this.target) return;\n this.draft[key] = value;\n this.callbacks.onApply(this.target.instanceId, { ...this.draft });\n }\n\n private resetDefaults(): void {\n if (!this.target) return;\n const reset: Record<string, IndicatorParamValue> = {};\n for (const [key, def] of Object.entries(this.target.defaults)) {\n reset[key] = def as IndicatorParamValue;\n }\n this.draft = reset;\n this.callbacks.onApply(this.target.instanceId, { ...reset });\n this.renderFields();\n }\n\n private renderFields(): void {\n this.bodyEl.replaceChildren();\n if (!this.target) return;\n\n const section = document.createElement('div');\n section.className = 'tcw-settings-section';\n\n const keys = Object.keys(this.target.defaults);\n if (keys.length === 0) {\n const empty = document.createElement('div');\n empty.className = 'tcw-settings-label';\n empty.textContent = 'This indicator has no adjustable parameters.';\n section.appendChild(empty);\n }\n\n for (const key of keys) {\n section.appendChild(this.fieldRow(key));\n }\n this.bodyEl.appendChild(section);\n }\n\n private fieldRow(key: string): HTMLDivElement {\n const row = document.createElement('div');\n row.className = 'tcw-settings-row';\n const label = document.createElement('span');\n label.className = 'tcw-settings-label';\n label.textContent = titleCase(key);\n row.appendChild(label);\n\n const value = this.currentValue(key);\n const defType = typeof (this.target?.defaults[key] ?? value);\n\n if (defType === 'boolean') {\n row.appendChild(this.toggleControl(key, Boolean(value)));\n } else if (defType === 'number') {\n row.appendChild(this.numberControl(key, Number(value)));\n } else if (typeof value === 'string' && HEX_RE.test(value)) {\n row.appendChild(this.colorControl(key, value));\n } else {\n row.appendChild(this.textControl(key, String(value ?? '')));\n }\n return row;\n }\n\n private toggleControl(key: string, value: boolean): HTMLButtonElement {\n const toggle = document.createElement('button');\n toggle.className = `tcw-toggle${value ? ' tcw-on' : ''}`;\n toggle.type = 'button';\n toggle.addEventListener('click', () => {\n const next = !toggle.classList.contains('tcw-on');\n toggle.classList.toggle('tcw-on', next);\n this.setValue(key, next);\n });\n return toggle;\n }\n\n private numberControl(key: string, value: number): HTMLInputElement {\n const input = document.createElement('input');\n input.type = 'number';\n input.className = 'tcw-indi-input';\n input.value = String(value);\n // Integer-looking defaults step by 1; fractional defaults step by 0.1.\n input.step = Number.isInteger(value) ? '1' : '0.1';\n input.addEventListener('change', () => {\n const n = Number(input.value);\n if (Number.isFinite(n)) this.setValue(key, n);\n });\n return input;\n }\n\n private colorControl(key: string, value: string): HTMLInputElement {\n const input = document.createElement('input');\n input.type = 'color';\n input.className = 'tcw-indi-color';\n input.value = value.length === 4 ? expandHex(value) : value;\n input.addEventListener('input', () => this.setValue(key, input.value));\n return input;\n }\n\n private textControl(key: string, value: string): HTMLInputElement {\n const input = document.createElement('input');\n input.type = 'text';\n input.className = 'tcw-indi-input';\n input.value = value;\n input.addEventListener('change', () => this.setValue(key, input.value));\n return input;\n }\n}\n\nfunction expandHex(short: string): string {\n // #abc → #aabbcc\n const r = short[1], g = short[2], b = short[3];\n return `#${r}${r}${g}${g}${b}${b}`;\n}\n","import type { DrawingStyle } from '@tradecanvas/commons';\n\nexport interface DrawingStyleTemplate {\n name: string;\n style: Partial<DrawingStyle>;\n}\n\n/** Minimal storage surface — satisfied by `localStorage` and easy to mock. */\nexport interface KeyValueStorage {\n getItem(key: string): string | null;\n setItem(key: string, value: string): void;\n}\n\nfunction defaultStorage(): KeyValueStorage | null {\n try {\n return typeof localStorage !== 'undefined' ? localStorage : null;\n } catch {\n return null;\n }\n}\n\nconst STYLE_KEYS: (keyof DrawingStyle)[] = [\n 'color', 'lineWidth', 'lineStyle', 'fillColor', 'fillOpacity', 'fontSize',\n];\n\n/** Keep only known style keys — guards against junk persisted by older builds. */\nfunction sanitizeStyle(raw: unknown): Partial<DrawingStyle> {\n if (!raw || typeof raw !== 'object') return {};\n const out: Partial<DrawingStyle> = {};\n const obj = raw as Record<string, unknown>;\n for (const key of STYLE_KEYS) {\n if (obj[key] !== undefined) (out as Record<string, unknown>)[key] = obj[key];\n }\n return out;\n}\n\n/**\n * Named drawing-style presets, persisted to a key-value store. Templates are\n * upserted by name (case-sensitive) and ordered most-recently-saved last.\n */\nexport class DrawingTemplateStore {\n private templates: DrawingStyleTemplate[] = [];\n\n constructor(\n private storageKey = 'tcw:draw-templates',\n private storage: KeyValueStorage | null = defaultStorage(),\n ) {\n this.load();\n }\n\n list(): DrawingStyleTemplate[] {\n return this.templates.map((t) => ({ name: t.name, style: { ...t.style } }));\n }\n\n get(name: string): DrawingStyleTemplate | null {\n const t = this.templates.find((x) => x.name === name);\n return t ? { name: t.name, style: { ...t.style } } : null;\n }\n\n /** Insert or replace a template by name. */\n save(name: string, style: Partial<DrawingStyle>): void {\n const trimmed = name.trim();\n if (!trimmed) return;\n const clean = sanitizeStyle(style);\n this.templates = this.templates.filter((t) => t.name !== trimmed);\n this.templates.push({ name: trimmed, style: clean });\n this.persist();\n }\n\n remove(name: string): void {\n const next = this.templates.filter((t) => t.name !== name);\n if (next.length === this.templates.length) return;\n this.templates = next;\n this.persist();\n }\n\n clear(): void {\n this.templates = [];\n this.persist();\n }\n\n private load(): void {\n if (!this.storage) return;\n try {\n const raw = this.storage.getItem(this.storageKey);\n if (!raw) return;\n const parsed = JSON.parse(raw);\n if (!Array.isArray(parsed)) return;\n this.templates = parsed\n .filter((t) => t && typeof t.name === 'string')\n .map((t) => ({ name: t.name, style: sanitizeStyle(t.style) }));\n } catch {\n // Corrupt or unavailable storage — start empty.\n }\n }\n\n private persist(): void {\n if (!this.storage) return;\n try {\n this.storage.setItem(this.storageKey, JSON.stringify(this.templates));\n } catch {\n // Storage full or blocked — keep the in-memory copy.\n }\n }\n}\n","import type { DrawingStyle } from '@tradecanvas/commons';\nimport { createIcon } from './icons.js';\nimport { DrawingTemplateStore } from './DrawingTemplateStore.js';\n\nexport interface DrawingStyleCallbacks {\n /** Apply a style change to the active (next) drawing and the selected one. */\n onStyleChange: (style: Partial<DrawingStyle>) => void;\n /** Current active drawing style, for seeding controls and saving templates. */\n getStyle: () => DrawingStyle;\n}\n\nconst SWATCHES = ['#2962ff', '#089981', '#f23645', '#ff9800', '#ab47bc', '#26c6da', '#ffffff', '#787b86'];\nconst WIDTHS = [1, 2, 3, 4];\nconst LINE_STYLES: DrawingStyle['lineStyle'][] = ['solid', 'dashed', 'dotted'];\n\n/**\n * Drawing style popover — pick colour, line width, and line style for the next\n * drawing (and the selected one), plus save/apply named style templates\n * persisted via `DrawingTemplateStore`.\n */\nexport class WidgetDrawingStyle {\n private el: HTMLDivElement;\n private templatesEl: HTMLDivElement;\n private nameInput: HTMLInputElement;\n private callbacks: DrawingStyleCallbacks;\n private store: DrawingTemplateStore;\n private open = false;\n\n constructor(host: HTMLElement, callbacks: DrawingStyleCallbacks, store: DrawingTemplateStore) {\n this.callbacks = callbacks;\n this.store = store;\n\n this.el = document.createElement('div');\n this.el.className = 'tcw-style-panel';\n this.el.hidden = true;\n\n const header = document.createElement('div');\n header.className = 'tcw-style-header';\n const title = document.createElement('span');\n title.textContent = 'Drawing Style';\n const closeBtn = document.createElement('button');\n closeBtn.type = 'button';\n closeBtn.className = 'tcw-style-close';\n closeBtn.setAttribute('aria-label', 'Close');\n closeBtn.innerHTML = createIcon('x', 14);\n closeBtn.addEventListener('click', () => this.close());\n header.appendChild(title);\n header.appendChild(closeBtn);\n this.el.appendChild(header);\n\n this.el.appendChild(this.colorRow());\n this.el.appendChild(this.widthRow());\n this.el.appendChild(this.lineStyleRow());\n\n // Templates\n const tmplHead = document.createElement('div');\n tmplHead.className = 'tcw-style-subhead';\n tmplHead.textContent = 'Templates';\n this.el.appendChild(tmplHead);\n\n const saveRow = document.createElement('div');\n saveRow.className = 'tcw-style-save';\n this.nameInput = document.createElement('input');\n this.nameInput.type = 'text';\n this.nameInput.placeholder = 'Template name';\n this.nameInput.className = 'tcw-style-name';\n const saveBtn = document.createElement('button');\n saveBtn.type = 'button';\n saveBtn.className = 'tcw-style-savebtn';\n saveBtn.innerHTML = `${createIcon('plus', 13)}<span>Save</span>`;\n saveBtn.addEventListener('click', () => this.saveTemplate());\n saveRow.appendChild(this.nameInput);\n saveRow.appendChild(saveBtn);\n this.el.appendChild(saveRow);\n\n this.templatesEl = document.createElement('div');\n this.templatesEl.className = 'tcw-style-templates';\n this.el.appendChild(this.templatesEl);\n\n host.appendChild(this.el);\n this.renderTemplates();\n }\n\n isOpen(): boolean {\n return this.open;\n }\n\n toggle(): void {\n this.open ? this.close() : this.openPanel();\n }\n\n openPanel(): void {\n this.open = true;\n this.el.hidden = false;\n this.syncActiveControls();\n this.renderTemplates();\n }\n\n close(): void {\n this.open = false;\n this.el.hidden = true;\n }\n\n destroy(): void {\n this.el.remove();\n }\n\n private colorRow(): HTMLDivElement {\n const row = document.createElement('div');\n row.className = 'tcw-style-row tcw-style-colors';\n for (const c of SWATCHES) {\n const sw = document.createElement('button');\n sw.type = 'button';\n sw.className = 'tcw-style-swatch';\n sw.style.background = c;\n sw.dataset.color = c;\n sw.setAttribute('aria-label', c);\n sw.addEventListener('click', () => this.applyStyle({ color: c }));\n row.appendChild(sw);\n }\n const picker = document.createElement('input');\n picker.type = 'color';\n picker.className = 'tcw-style-picker';\n picker.addEventListener('input', () => this.applyStyle({ color: picker.value }));\n row.appendChild(picker);\n return row;\n }\n\n private widthRow(): HTMLDivElement {\n const row = document.createElement('div');\n row.className = 'tcw-style-row tcw-style-widths';\n for (const w of WIDTHS) {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'tcw-style-width';\n btn.dataset.width = String(w);\n const bar = document.createElement('span');\n bar.style.height = `${w}px`;\n btn.appendChild(bar);\n btn.addEventListener('click', () => this.applyStyle({ lineWidth: w }));\n row.appendChild(btn);\n }\n return row;\n }\n\n private lineStyleRow(): HTMLDivElement {\n const row = document.createElement('div');\n row.className = 'tcw-style-row tcw-style-dashes';\n for (const ls of LINE_STYLES) {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'tcw-style-dash';\n btn.dataset.linestyle = ls;\n btn.textContent = ls === 'solid' ? '──' : ls === 'dashed' ? '╌╌' : '┄┄';\n btn.title = ls;\n btn.addEventListener('click', () => this.applyStyle({ lineStyle: ls }));\n row.appendChild(btn);\n }\n return row;\n }\n\n private applyStyle(patch: Partial<DrawingStyle>): void {\n this.callbacks.onStyleChange(patch);\n this.syncActiveControls();\n }\n\n /** Mark the controls matching the current active style. */\n private syncActiveControls(): void {\n const style = this.callbacks.getStyle();\n this.el.querySelectorAll<HTMLElement>('.tcw-style-swatch').forEach((sw) => {\n sw.classList.toggle('tcw-on', sw.dataset.color?.toLowerCase() === style.color?.toLowerCase());\n });\n this.el.querySelectorAll<HTMLElement>('.tcw-style-width').forEach((b) => {\n b.classList.toggle('tcw-on', Number(b.dataset.width) === style.lineWidth);\n });\n this.el.querySelectorAll<HTMLElement>('.tcw-style-dash').forEach((b) => {\n b.classList.toggle('tcw-on', b.dataset.linestyle === style.lineStyle);\n });\n }\n\n private saveTemplate(): void {\n const name = this.nameInput.value.trim();\n if (!name) return;\n this.store.save(name, this.callbacks.getStyle());\n this.nameInput.value = '';\n this.renderTemplates();\n }\n\n private renderTemplates(): void {\n this.templatesEl.replaceChildren();\n const templates = this.store.list();\n if (templates.length === 0) {\n const empty = document.createElement('div');\n empty.className = 'tcw-style-empty';\n empty.textContent = 'No saved templates';\n this.templatesEl.appendChild(empty);\n return;\n }\n for (const t of templates) {\n const row = document.createElement('div');\n row.className = 'tcw-style-template';\n\n const apply = document.createElement('button');\n apply.type = 'button';\n apply.className = 'tcw-style-apply';\n const dot = document.createElement('span');\n dot.className = 'tcw-style-tdot';\n dot.style.background = (t.style.color as string) ?? 'var(--tcw-text-muted)';\n const label = document.createElement('span');\n label.textContent = t.name;\n apply.appendChild(dot);\n apply.appendChild(label);\n apply.addEventListener('click', () => {\n this.callbacks.onStyleChange({ ...t.style });\n this.syncActiveControls();\n });\n\n const del = document.createElement('button');\n del.type = 'button';\n del.className = 'tcw-style-tdel';\n del.setAttribute('aria-label', 'Delete template');\n del.innerHTML = createIcon('trash', 13);\n del.addEventListener('click', () => {\n this.store.remove(t.name);\n this.renderTemplates();\n });\n\n row.appendChild(apply);\n row.appendChild(del);\n this.templatesEl.appendChild(row);\n }\n }\n}\n","import type { KeyValueStorage } from './DrawingTemplateStore.js';\n\nfunction defaultStorage(): KeyValueStorage | null {\n try {\n return typeof localStorage !== 'undefined' ? localStorage : null;\n } catch {\n return null;\n }\n}\n\n/**\n * An ordered, de-duplicated set of pinned drawing-tool ids, persisted to a\n * key-value store. Order is insertion order (most-recently-pinned last).\n */\nexport class DrawingFavoritesStore {\n private favorites: string[] = [];\n\n constructor(\n private storageKey = 'tcw:draw-favorites',\n private storage: KeyValueStorage | null = defaultStorage(),\n ) {\n this.load();\n }\n\n list(): string[] {\n return [...this.favorites];\n }\n\n has(tool: string): boolean {\n return this.favorites.includes(tool);\n }\n\n add(tool: string): void {\n if (!tool || this.favorites.includes(tool)) return;\n this.favorites = [...this.favorites, tool];\n this.persist();\n }\n\n remove(tool: string): void {\n if (!this.favorites.includes(tool)) return;\n this.favorites = this.favorites.filter((t) => t !== tool);\n this.persist();\n }\n\n /** Toggle a tool's pinned state. Returns the new state (true = pinned). */\n toggle(tool: string): boolean {\n if (this.has(tool)) {\n this.remove(tool);\n return false;\n }\n this.add(tool);\n return true;\n }\n\n /** Seed the favorites only when none are stored yet (first run). */\n seedDefaults(tools: string[]): void {\n if (this.favorites.length > 0) return;\n this.favorites = [...new Set(tools.filter(Boolean))];\n this.persist();\n }\n\n private load(): void {\n if (!this.storage) return;\n try {\n const raw = this.storage.getItem(this.storageKey);\n if (!raw) return;\n const parsed = JSON.parse(raw);\n if (Array.isArray(parsed)) {\n this.favorites = [...new Set(parsed.filter((t) => typeof t === 'string'))];\n }\n } catch {\n // Corrupt or unavailable — start empty.\n }\n }\n\n private persist(): void {\n if (!this.storage) return;\n try {\n this.storage.setItem(this.storageKey, JSON.stringify(this.favorites));\n } catch {\n // Storage full or blocked — keep the in-memory copy.\n }\n }\n}\n","import { createIcon } from './icons.js';\n\nexport interface BracketBarCallbacks {\n onConfirm: () => void;\n onCancel: () => void;\n}\n\n/**\n * Floating confirm/cancel bar shown while a bracket order is being placed.\n * The live entry / SL / TP numbers are drawn on the chart canvas; this bar\n * just carries the commit and discard actions (also bound to Enter / Esc).\n */\nexport class WidgetBracketBar {\n private el: HTMLDivElement;\n private labelEl: HTMLSpanElement;\n private callbacks: BracketBarCallbacks;\n private visible = false;\n\n constructor(host: HTMLElement, callbacks: BracketBarCallbacks) {\n this.callbacks = callbacks;\n\n this.el = document.createElement('div');\n this.el.className = 'tcw-bracket-bar';\n this.el.hidden = true;\n\n this.labelEl = document.createElement('span');\n this.labelEl.className = 'tcw-bracket-label';\n this.el.appendChild(this.labelEl);\n\n const hint = document.createElement('span');\n hint.className = 'tcw-bracket-hint';\n hint.textContent = 'drag lines to adjust';\n this.el.appendChild(hint);\n\n const cancel = document.createElement('button');\n cancel.type = 'button';\n cancel.className = 'tcw-bracket-cancel';\n cancel.innerHTML = `${createIcon('x', 14)}<span>Cancel</span>`;\n cancel.addEventListener('click', () => this.callbacks.onCancel());\n\n const confirm = document.createElement('button');\n confirm.type = 'button';\n confirm.className = 'tcw-bracket-confirm';\n confirm.innerHTML = `${createIcon('check', 14)}<span>Place</span>`;\n confirm.addEventListener('click', () => this.callbacks.onConfirm());\n\n this.el.appendChild(cancel);\n this.el.appendChild(confirm);\n host.appendChild(this.el);\n }\n\n show(side: 'buy' | 'sell'): void {\n this.visible = true;\n this.labelEl.textContent = side === 'buy' ? 'Long bracket' : 'Short bracket';\n this.labelEl.dataset.side = side;\n this.el.hidden = false;\n }\n\n hide(): void {\n this.visible = false;\n this.el.hidden = true;\n }\n\n isVisible(): boolean {\n return this.visible;\n }\n\n destroy(): void {\n this.el.remove();\n }\n}\n","export interface AlertNotifyOptions {\n /** Play a sound on trigger. `true` = built-in beep, string = audio URL. Default `false`. */\n sound?: boolean | string;\n /** Show a desktop notification (requests permission on first use). Default `false`. */\n desktop?: boolean;\n /** Title for desktop notifications. Default `'Price alert'`. */\n title?: string;\n}\n\n/** True when the Notification API is present and not denied. */\nexport function canRequestNotifications(): boolean {\n return typeof Notification !== 'undefined' && Notification.permission !== 'denied';\n}\n\n/**\n * Plays a sound and/or raises a desktop notification when a price alert fires.\n * Browser-API heavy by nature — every entry point is guarded so it degrades to\n * a no-op in SSR, unsupported browsers, or when permission is denied.\n */\nexport class AlertNotifier {\n private options: AlertNotifyOptions;\n private audioCtx: AudioContext | null = null;\n private audioEl: HTMLAudioElement | null = null;\n private permissionAsked = false;\n\n constructor(options: AlertNotifyOptions = {}) {\n this.options = options;\n if (typeof options.sound === 'string') {\n try {\n this.audioEl = new Audio(options.sound);\n this.audioEl.preload = 'auto';\n } catch {\n this.audioEl = null;\n }\n }\n // Request notification permission up front so the first alert isn't silent.\n if (options.desktop) this.ensurePermission();\n }\n\n setOptions(options: AlertNotifyOptions): void {\n this.options = { ...this.options, ...options };\n }\n\n /** Fire the configured notifications for a triggered alert. */\n notify(message: string): void {\n if (this.options.sound) this.playSound();\n if (this.options.desktop) this.showDesktop(message);\n }\n\n private playSound(): void {\n if (this.audioEl) {\n this.audioEl.currentTime = 0;\n void this.audioEl.play().catch(() => {});\n return;\n }\n this.beep();\n }\n\n /** A short two-tone beep via Web Audio — no asset required. */\n private beep(): void {\n try {\n const Ctx = window.AudioContext ?? (window as unknown as { webkitAudioContext?: typeof AudioContext }).webkitAudioContext;\n if (!Ctx) return;\n if (!this.audioCtx) this.audioCtx = new Ctx();\n const ctx = this.audioCtx;\n const now = ctx.currentTime;\n const gain = ctx.createGain();\n gain.gain.setValueAtTime(0.0001, now);\n gain.gain.exponentialRampToValueAtTime(0.2, now + 0.01);\n gain.gain.exponentialRampToValueAtTime(0.0001, now + 0.35);\n gain.connect(ctx.destination);\n const osc = ctx.createOscillator();\n osc.type = 'sine';\n osc.frequency.setValueAtTime(880, now);\n osc.frequency.setValueAtTime(1320, now + 0.16);\n osc.connect(gain);\n osc.start(now);\n osc.stop(now + 0.36);\n } catch {\n // Audio unavailable or blocked by autoplay policy — silent.\n }\n }\n\n private ensurePermission(): void {\n if (this.permissionAsked) return;\n this.permissionAsked = true;\n if (typeof Notification === 'undefined') return;\n if (Notification.permission === 'default') {\n void Notification.requestPermission().catch(() => {});\n }\n }\n\n private showDesktop(message: string): void {\n if (typeof Notification === 'undefined') return;\n if (Notification.permission !== 'granted') {\n this.ensurePermission();\n return;\n }\n try {\n new Notification(this.options.title ?? 'Price alert', { body: message });\n } catch {\n // Some browsers throw if not invoked from a user gesture — ignore.\n }\n }\n\n destroy(): void {\n try {\n void this.audioCtx?.close();\n } catch {\n // ignore\n }\n this.audioCtx = null;\n this.audioEl = null;\n }\n}\n","import type { DepthData } from '@tradecanvas/commons';\n\nexport interface LadderRow {\n price: number;\n bidVolume: number;\n askVolume: number;\n}\n\nexport interface LadderModel {\n /** Rows ordered high → low price (asks on top, bids below). */\n rows: LadderRow[];\n /** Largest single-side volume across the shown rows (for bar scaling). */\n maxVolume: number;\n /** Midpoint between best bid and best ask, or null if a side is empty. */\n mid: number | null;\n}\n\n/**\n * Build a depth-of-market ladder from an order book: the best `maxLevels` asks\n * (lowest prices) and best `maxLevels` bids (highest prices), merged into rows\n * ordered high→low. A price present on both sides is merged into one row.\n */\nexport function buildLadderRows(data: DepthData, maxLevels = 12): LadderModel {\n const asks = [...data.asks].sort((a, b) => a.price - b.price).slice(0, maxLevels);\n const bids = [...data.bids].sort((a, b) => b.price - a.price).slice(0, maxLevels);\n\n const bestAsk = asks.length > 0 ? asks[0].price : null;\n const bestBid = bids.length > 0 ? bids[0].price : null;\n const mid = bestAsk !== null && bestBid !== null ? (bestAsk + bestBid) / 2 : null;\n\n const byPrice = new Map<number, LadderRow>();\n const rowAt = (price: number): LadderRow => {\n let row = byPrice.get(price);\n if (!row) {\n row = { price, bidVolume: 0, askVolume: 0 };\n byPrice.set(price, row);\n }\n return row;\n };\n for (const a of asks) rowAt(a.price).askVolume += a.volume;\n for (const b of bids) rowAt(b.price).bidVolume += b.volume;\n\n const rows = [...byPrice.values()].sort((a, b) => b.price - a.price);\n let maxVolume = 0;\n for (const r of rows) maxVolume = Math.max(maxVolume, r.bidVolume, r.askVolume);\n\n return { rows, maxVolume, mid };\n}\n","import type { DepthData } from '@tradecanvas/commons';\nimport { createIcon } from './icons.js';\nimport { buildLadderRows, type LadderModel } from './ladderRows.js';\n\nexport interface DepthLadderCallbacks {\n /** Buy at `price` (clicked an ask cell) or sell at `price` (clicked a bid cell). */\n onTrade: (side: 'buy' | 'sell', price: number) => void;\n formatPrice: (price: number) => string;\n}\n\n/**\n * Depth-of-market ladder (DOM). Renders the order book as price rows with bid\n * and ask size columns; clicking an ask cell buys at that price, a bid cell\n * sells. Fed by `setData(depth)`; the bar widths scale to the largest visible\n * size.\n */\nexport class WidgetDepthLadder {\n private el: HTMLDivElement;\n private bodyEl: HTMLDivElement;\n private callbacks: DepthLadderCallbacks;\n private open = false;\n private levels: number;\n\n constructor(host: HTMLElement, callbacks: DepthLadderCallbacks, levels = 12) {\n this.callbacks = callbacks;\n this.levels = levels;\n\n this.el = document.createElement('div');\n this.el.className = 'tcw-ladder';\n this.el.hidden = true;\n\n const header = document.createElement('div');\n header.className = 'tcw-ladder-header';\n const title = document.createElement('span');\n title.textContent = 'Depth Ladder';\n const closeBtn = document.createElement('button');\n closeBtn.type = 'button';\n closeBtn.className = 'tcw-ladder-close';\n closeBtn.setAttribute('aria-label', 'Close');\n closeBtn.innerHTML = createIcon('x', 14);\n closeBtn.addEventListener('click', () => this.close());\n header.appendChild(title);\n header.appendChild(closeBtn);\n this.el.appendChild(header);\n\n const cols = document.createElement('div');\n cols.className = 'tcw-ladder-cols';\n cols.innerHTML = '<span>Bid</span><span>Price</span><span>Ask</span>';\n this.el.appendChild(cols);\n\n this.bodyEl = document.createElement('div');\n this.bodyEl.className = 'tcw-ladder-body';\n this.el.appendChild(this.bodyEl);\n\n host.appendChild(this.el);\n }\n\n isOpen(): boolean {\n return this.open;\n }\n\n toggle(): void {\n this.open ? this.close() : this.openPanel();\n }\n\n openPanel(): void {\n this.open = true;\n this.el.hidden = false;\n }\n\n close(): void {\n this.open = false;\n this.el.hidden = true;\n }\n\n setData(depth: DepthData | null): void {\n if (!depth) {\n this.renderEmpty();\n return;\n }\n this.render(buildLadderRows(depth, this.levels));\n }\n\n destroy(): void {\n this.el.remove();\n }\n\n private renderEmpty(): void {\n this.bodyEl.replaceChildren();\n const empty = document.createElement('div');\n empty.className = 'tcw-ladder-empty';\n empty.textContent = 'No order-book data';\n this.bodyEl.appendChild(empty);\n }\n\n private render(model: LadderModel): void {\n this.bodyEl.replaceChildren();\n if (model.rows.length === 0) {\n this.renderEmpty();\n return;\n }\n const inv = model.maxVolume > 0 ? 1 / model.maxVolume : 0;\n\n for (const row of model.rows) {\n const isAsk = row.askVolume > 0;\n const tr = document.createElement('div');\n tr.className = 'tcw-ladder-row';\n\n // Bid cell (click → sell at price)\n const bid = document.createElement('button');\n bid.type = 'button';\n bid.className = 'tcw-ladder-cell tcw-ladder-bid';\n if (row.bidVolume > 0) {\n bid.textContent = formatSize(row.bidVolume);\n bid.style.setProperty('--w', `${(row.bidVolume * inv * 100).toFixed(1)}%`);\n bid.title = `Sell @ ${this.callbacks.formatPrice(row.price)}`;\n bid.addEventListener('click', () => this.callbacks.onTrade('sell', row.price));\n } else {\n bid.disabled = true;\n }\n\n const price = document.createElement('div');\n price.className = `tcw-ladder-price ${isAsk ? 'tcw-ask' : 'tcw-bid'}`;\n price.textContent = this.callbacks.formatPrice(row.price);\n\n // Ask cell (click → buy at price)\n const ask = document.createElement('button');\n ask.type = 'button';\n ask.className = 'tcw-ladder-cell tcw-ladder-ask';\n if (row.askVolume > 0) {\n ask.textContent = formatSize(row.askVolume);\n ask.style.setProperty('--w', `${(row.askVolume * inv * 100).toFixed(1)}%`);\n ask.title = `Buy @ ${this.callbacks.formatPrice(row.price)}`;\n ask.addEventListener('click', () => this.callbacks.onTrade('buy', row.price));\n } else {\n ask.disabled = true;\n }\n\n tr.appendChild(bid);\n tr.appendChild(price);\n tr.appendChild(ask);\n this.bodyEl.appendChild(tr);\n }\n }\n}\n\nfunction formatSize(v: number): string {\n if (v >= 1000) return (v / 1000).toFixed(1) + 'k';\n if (v >= 1) return v.toFixed(2).replace(/\\.00$/, '');\n return v.toPrecision(2);\n}\n","import { createIcon } from './icons.js';\n\nexport interface DataWindowIndicator {\n name: string;\n values: { key: string; value: number }[];\n}\n\nexport interface DataWindowModel {\n ohlc: { open: number; high: number; low: number; close: number; volume: number } | null;\n change: number;\n changePct: number;\n indicators: DataWindowIndicator[];\n}\n\nexport interface DataWindowCallbacks {\n formatPrice: (price: number) => string;\n}\n\n/**\n * Data Window — a floating readout of the exact O/H/L/C/V, change, and every\n * active indicator value at the hovered bar. Updated from `crosshairMove`.\n */\nexport class WidgetDataWindow {\n private el: HTMLDivElement;\n private bodyEl: HTMLDivElement;\n private callbacks: DataWindowCallbacks;\n private open = false;\n\n constructor(host: HTMLElement, callbacks: DataWindowCallbacks) {\n this.callbacks = callbacks;\n\n this.el = document.createElement('div');\n this.el.className = 'tcw-datawin';\n this.el.hidden = true;\n\n const header = document.createElement('div');\n header.className = 'tcw-datawin-header';\n const title = document.createElement('span');\n title.textContent = 'Data Window';\n const closeBtn = document.createElement('button');\n closeBtn.type = 'button';\n closeBtn.className = 'tcw-datawin-close';\n closeBtn.setAttribute('aria-label', 'Close');\n closeBtn.innerHTML = createIcon('x', 14);\n closeBtn.addEventListener('click', () => this.close());\n header.appendChild(title);\n header.appendChild(closeBtn);\n this.el.appendChild(header);\n\n this.bodyEl = document.createElement('div');\n this.bodyEl.className = 'tcw-datawin-body';\n this.el.appendChild(this.bodyEl);\n\n host.appendChild(this.el);\n }\n\n isOpen(): boolean {\n return this.open;\n }\n\n toggle(): void {\n this.open ? this.close() : this.openPanel();\n }\n\n openPanel(): void {\n this.open = true;\n this.el.hidden = false;\n }\n\n close(): void {\n this.open = false;\n this.el.hidden = true;\n }\n\n destroy(): void {\n this.el.remove();\n }\n\n render(model: DataWindowModel): void {\n if (!this.open) return;\n this.bodyEl.replaceChildren();\n\n if (!model.ohlc) {\n const empty = document.createElement('div');\n empty.className = 'tcw-datawin-empty';\n empty.textContent = 'Hover the chart';\n this.bodyEl.appendChild(empty);\n return;\n }\n\n const fp = this.callbacks.formatPrice;\n const o = model.ohlc;\n this.bodyEl.appendChild(this.row('Open', fp(o.open)));\n this.bodyEl.appendChild(this.row('High', fp(o.high)));\n this.bodyEl.appendChild(this.row('Low', fp(o.low)));\n this.bodyEl.appendChild(this.row('Close', fp(o.close)));\n const tone = model.change > 0 ? 'up' : model.change < 0 ? 'down' : '';\n const sign = model.change > 0 ? '+' : '';\n this.bodyEl.appendChild(this.row('Change', `${sign}${fp(model.change)} (${sign}${model.changePct.toFixed(2)}%)`, tone));\n this.bodyEl.appendChild(this.row('Volume', formatVolume(o.volume)));\n\n for (const ind of model.indicators) {\n const head = document.createElement('div');\n head.className = 'tcw-datawin-sub';\n head.textContent = ind.name;\n this.bodyEl.appendChild(head);\n for (const v of ind.values) {\n this.bodyEl.appendChild(this.row(v.key, formatNumber(v.value)));\n }\n }\n }\n\n private row(label: string, value: string, tone = ''): HTMLDivElement {\n const row = document.createElement('div');\n row.className = 'tcw-datawin-row';\n const l = document.createElement('span');\n l.className = 'tcw-datawin-label';\n l.textContent = label;\n const v = document.createElement('span');\n v.className = `tcw-datawin-value${tone ? ` tcw-${tone}` : ''}`;\n v.textContent = value;\n row.appendChild(l);\n row.appendChild(v);\n return row;\n }\n}\n\nfunction formatNumber(v: number): string {\n if (!Number.isFinite(v)) return '—';\n const abs = Math.abs(v);\n if (abs >= 1000) return v.toFixed(2);\n if (abs >= 1) return v.toFixed(4);\n return v.toPrecision(4);\n}\n\nfunction formatVolume(v: number): string {\n if (v >= 1_000_000_000) return (v / 1_000_000_000).toFixed(2) + 'B';\n if (v >= 1_000_000) return (v / 1_000_000).toFixed(2) + 'M';\n if (v >= 1_000) return (v / 1_000).toFixed(2) + 'K';\n return v.toFixed(0);\n}\n","import type { ChartType, TimeFrame, DrawingState, PriceScaleMode } from '@tradecanvas/commons';\n\nexport interface ShareableIndicator {\n id: string;\n params: Record<string, number | string | boolean>;\n}\n\nexport interface ShareableWidgetState {\n v: 1;\n symbol: string;\n timeframe: TimeFrame;\n chartType: ChartType;\n scaleMode: PriceScaleMode;\n indicators: ShareableIndicator[];\n drawings: DrawingState[];\n}\n\ninterface NodeBufferCtor {\n from(input: string, encoding: string): { toString(encoding: string): string };\n}\nconst nodeBuffer = (globalThis as { Buffer?: NodeBufferCtor }).Buffer;\n\nfunction utf8ToBase64(str: string): string {\n if (nodeBuffer) return nodeBuffer.from(str, 'utf8').toString('base64');\n const bytes = new TextEncoder().encode(str);\n let bin = '';\n for (const b of bytes) bin += String.fromCharCode(b);\n return btoa(bin);\n}\n\nfunction base64ToUtf8(b64: string): string {\n if (nodeBuffer) return nodeBuffer.from(b64, 'base64').toString('utf8');\n const bin = atob(b64);\n const bytes = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i);\n return new TextDecoder().decode(bytes);\n}\n\nfunction toBase64Url(b64: string): string {\n return b64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\nfunction fromBase64Url(s: string): string {\n const b64 = s.replace(/-/g, '+').replace(/_/g, '/');\n const pad = b64.length % 4 === 0 ? '' : '='.repeat(4 - (b64.length % 4));\n return b64 + pad;\n}\n\n/** Encode a shareable widget state to a compact, URL-safe string. */\nexport function encodeWidgetState(state: ShareableWidgetState): string {\n return toBase64Url(utf8ToBase64(JSON.stringify(state)));\n}\n\n/**\n * Decode a shareable-state string. Returns null for anything malformed or of an\n * unknown version — callers should treat null as \"ignore and keep current view\".\n */\nexport function decodeWidgetState(encoded: string): ShareableWidgetState | null {\n if (!encoded) return null;\n try {\n const json = base64ToUtf8(fromBase64Url(encoded));\n const obj = JSON.parse(json);\n if (!obj || obj.v !== 1 || typeof obj.symbol !== 'string') return null;\n return {\n v: 1,\n symbol: obj.symbol,\n timeframe: obj.timeframe,\n chartType: obj.chartType,\n scaleMode: obj.scaleMode ?? 'regular',\n indicators: Array.isArray(obj.indicators) ? obj.indicators : [],\n drawings: Array.isArray(obj.drawings) ? obj.drawings : [],\n };\n } catch {\n return null;\n }\n}\n\nconst HASH_KEY = 'tcw';\n\n/** Read a `#tcw=<encoded>` fragment from a URL hash, or null. */\nexport function readShareHash(hash: string): string | null {\n const clean = hash.startsWith('#') ? hash.slice(1) : hash;\n for (const part of clean.split('&')) {\n const eq = part.indexOf('=');\n if (eq > 0 && part.slice(0, eq) === HASH_KEY) return decodeURIComponent(part.slice(eq + 1));\n }\n return null;\n}\n\n/** Build a shareable URL by replacing the `tcw` hash param on `base`. */\nexport function buildShareUrl(base: string, encoded: string): string {\n const [withoutHash] = base.split('#');\n return `${withoutHash}#${HASH_KEY}=${encoded}`;\n}\n","import type { ChartType, DrawingToolType, Theme, TimeFrame } from '@tradecanvas/commons';\r\nimport { Chart } from '../Chart.js';\r\nimport { DARK_THEME, LIGHT_THEME } from '@tradecanvas/commons';\r\nimport type { ChartWidgetOptions, WidgetState, ChartSettingsState } from './types.js';\r\nimport { TIMEFRAMES, CHART_TYPES, INDICATORS, POPULAR_INDICATORS, DRAWING_TOOL_GROUPS, DEFAULT_SYMBOLS, DEFAULT_SETTINGS } from './widgetConfig.js';\r\nimport { injectWidgetStyles, removeWidgetStyles } from './WidgetStyles.js';\r\nimport { WidgetToolbar } from './WidgetToolbar.js';\r\nimport { WidgetDrawingSidebar } from './WidgetDrawingSidebar.js';\r\nimport { WidgetSettings } from './WidgetSettings.js';\r\nimport { WidgetStatusBar } from './WidgetStatusBar.js';\r\nimport { WidgetCommandPalette } from './WidgetCommandPalette.js';\r\nimport { WidgetSymbolSearch } from './WidgetSymbolSearch.js';\r\nimport { WidgetHotkeySheet } from './WidgetHotkeySheet.js';\r\nimport { WidgetReplayBar } from './WidgetReplayBar.js';\r\nimport { WidgetWatchlist, type WatchlistEntry } from './WidgetWatchlist.js';\r\nimport { WidgetAlertsPanel } from './WidgetAlertsPanel.js';\r\nimport { WidgetObjectTree, drawingTypeLabel } from './WidgetObjectTree.js';\r\nimport { WidgetIndicatorSettings } from './WidgetIndicatorSettings.js';\r\nimport { WidgetDrawingStyle } from './WidgetDrawingStyle.js';\r\nimport { DrawingTemplateStore } from './DrawingTemplateStore.js';\r\nimport { DrawingFavoritesStore } from './DrawingFavoritesStore.js';\r\nimport { WidgetBracketBar } from './WidgetBracketBar.js';\r\nimport { AlertNotifier } from './AlertNotifier.js';\r\nimport { WidgetDepthLadder } from './WidgetDepthLadder.js';\r\nimport { WidgetDataWindow, type DataWindowModel } from './WidgetDataWindow.js';\r\nimport type { DepthData } from '@tradecanvas/commons';\r\nimport { encodeWidgetState, decodeWidgetState, readShareHash, buildShareUrl } from './widgetShareState.js';\r\nimport { DragDropImporter, resampleOHLCV, inferTimeframeMs } from '../io/index.js';\r\nimport type { DataSeries } from '@tradecanvas/commons';\r\nimport { timeframeToMs } from '@tradecanvas/commons';\r\nimport type { CommandItem } from './WidgetCommandPalette.js';\r\n\r\n/** Distinct line colors for comparison overlays, cycled by add order. */\r\nconst COMPARE_COLORS = ['#f7931a', '#627eea', '#26a17b', '#e84142', '#8247e5', '#f3ba2f'];\r\n\r\nexport class ChartWidget {\r\n private chart: Chart;\r\n private state: WidgetState;\r\n private toolbar: WidgetToolbar | null = null;\r\n private sidebar: WidgetDrawingSidebar | null = null;\r\n private settings: WidgetSettings | null = null;\r\n private statusBar: WidgetStatusBar | null = null;\r\n private commandPalette: WidgetCommandPalette | null = null;\r\n private symbolSearch: WidgetSymbolSearch | null = null;\r\n private hotkeySheet: WidgetHotkeySheet | null = null;\r\n private replayBar: WidgetReplayBar | null = null;\r\n private dragDrop: DragDropImporter | null = null;\r\n private alertsPanel: WidgetAlertsPanel | null = null;\r\n private objectTree: WidgetObjectTree | null = null;\r\n private indicatorSettings: WidgetIndicatorSettings | null = null;\r\n private drawingStyle: WidgetDrawingStyle | null = null;\r\n private bracketBar: WidgetBracketBar | null = null;\r\n private alertNotifier: AlertNotifier | null = null;\r\n private depthLadder: WidgetDepthLadder | null = null;\r\n private dataWindow: WidgetDataWindow | null = null;\r\n private lastHoverIndex: number | null = null;\r\n private favoritesStore = new DrawingFavoritesStore();\r\n private watchlist: WidgetWatchlist | null = null;\r\n private watchlistSparkBuffer = new Map<string, number[]>();\r\n private sessionRefPrice: number | null = null;\r\n private watchlistInterval: ReturnType<typeof setInterval> | null = null;\r\n private replayOriginalData: DataSeries | null = null;\r\n private replayPollInterval: ReturnType<typeof setInterval> | null = null;\r\n private replaySpeed = 5;\r\n private layoutKeyPrefix: string | null = null;\r\n private layoutDebounceMs = 1500;\r\n private activeLayoutKey: string | null = null;\r\n private root: HTMLDivElement;\r\n private chartContainer: HTMLDivElement;\r\n private destroyed = false;\r\n private options: ChartWidgetOptions;\r\n private symbols: string[];\r\n private settingsState: ChartSettingsState;\r\n private adapter: import('@tradecanvas/commons').DataAdapter | null = null;\r\n private boundGlobalKeydown: ((e: KeyboardEvent) => void) | null = null;\r\n // Finest-resolution series the widget has seen. When no live adapter is\r\n // attached, switching to a coarser timeframe resamples from this base\r\n // instead of refetching. See `setData` / `applyTimeframeData`.\r\n private baseSeries: DataSeries | null = null;\r\n private baseTimeframeMs = 0;\r\n private compares: { id: string; symbol: string; color: string }[] = [];\r\n\r\n constructor(container: HTMLElement, options: ChartWidgetOptions = {}) {\r\n this.options = options;\r\n this.symbols = options.symbols ?? DEFAULT_SYMBOLS;\r\n this.settingsState = { ...DEFAULT_SETTINGS };\r\n\r\n // Resolve layout persistence config. Treated as opt-in — defaults to\r\n // `false` so existing apps don't suddenly start writing to localStorage.\r\n if (options.persistLayouts) {\r\n const cfg = options.persistLayouts === true ? {} : options.persistLayouts;\r\n this.layoutKeyPrefix = cfg.keyPrefix ?? 'tcw:layout:';\r\n this.layoutDebounceMs = cfg.debounceMs ?? 1500;\r\n }\r\n\r\n // Resolve theme\r\n const isDark = this.resolveIsDark(options.theme);\r\n const resolvedTheme = this.resolveTheme(options.theme);\r\n\r\n // Initialize state\r\n this.state = {\r\n symbol: options.symbol ?? this.symbols[0] ?? 'BTCUSDT',\r\n timeframe: options.timeframe ?? '5m',\r\n chartType: options.chartOptions?.chartType ?? 'candlestick',\r\n isDark,\r\n activeIndicators: new Map(),\r\n activeTool: null,\r\n magnetEnabled: true,\r\n connectionState: 'connecting',\r\n connectionMessage: 'Connecting...',\r\n };\r\n\r\n\r\n // 1. Inject styles\r\n injectWidgetStyles();\r\n\r\n // 2. Create DOM skeleton\r\n this.root = document.createElement('div');\r\n this.root.className = 'tcw-root';\r\n this.root.dataset.tcwTheme = isDark ? 'dark' : 'light';\r\n container.appendChild(this.root);\r\n\r\n // 3. Create toolbar\r\n if (options.toolbar !== false) {\r\n this.toolbar = new WidgetToolbar(\r\n this.root,\r\n {\r\n symbols: this.symbols,\r\n timeframes: options.timeframes\r\n ? TIMEFRAMES.filter(tf => (options.timeframes as TimeFrame[]).includes(tf.value))\r\n : TIMEFRAMES,\r\n chartTypes: options.chartTypes\r\n ? CHART_TYPES.filter(ct => (options.chartTypes as ChartType[]).includes(ct.value))\r\n : CHART_TYPES,\r\n indicators: INDICATORS,\r\n popularIndicatorIds: POPULAR_INDICATORS,\r\n },\r\n {\r\n onSymbolClick: () => this.handleSymbolClick(),\r\n onTimeframe: (tf) => this.handleTimeframe(tf),\r\n onChartType: (type) => this.handleChartType(type),\r\n onAddIndicator: (id) => this.handleAddIndicator(id),\r\n onRemoveIndicator: (iid) => this.handleRemoveIndicator(iid),\r\n onScreenshot: () => this.chart.screenshot(),\r\n onSettings: () => this.openSettings(),\r\n onToggleTheme: () => this.handleToggleTheme(),\r\n onToggleReplay: () => this.toggleReplay(),\r\n onToggleAlerts: options.alerts !== false ? () => this.toggleAlerts() : undefined,\r\n onToggleObjects: options.objectTree !== false ? () => this.toggleObjects() : undefined,\r\n onBracket: options.trading !== false ? (side) => this.startBracket(side) : undefined,\r\n onToggleLadder: options.trading !== false && options.depthLadder ? () => this.depthLadder?.toggle() : undefined,\r\n },\r\n );\r\n }\r\n\r\n // 4. Create body\r\n const body = document.createElement('div');\r\n body.className = 'tcw-body';\r\n\r\n if (options.drawingTools !== false) {\r\n if (options.drawingFavorites) this.favoritesStore.seedDefaults(options.drawingFavorites);\r\n this.sidebar = new WidgetDrawingSidebar(\r\n body,\r\n { drawingToolGroups: DRAWING_TOOL_GROUPS, favorites: this.favoritesStore.list() as DrawingToolType[] },\r\n {\r\n onDrawingTool: (tool) => this.handleDrawingTool(tool),\r\n onCancelDrawing: () => this.handleCancelDrawing(),\r\n onToggleMagnet: () => this.handleToggleMagnet(),\r\n onToggleFavorite: (tool) => this.handleToggleFavorite(tool),\r\n onUndo: () => this.chart.undo(),\r\n onRedo: () => this.chart.redo(),\r\n onClearDrawings: () => {\r\n this.chart.clearDrawings();\r\n this.state = { ...this.state, activeTool: null };\r\n this.updateUI();\r\n },\r\n onToggleStyle: () => this.drawingStyle?.toggle(),\r\n },\r\n );\r\n }\r\n\r\n this.chartContainer = document.createElement('div');\r\n this.chartContainer.className = 'tcw-chart-container';\r\n body.appendChild(this.chartContainer);\r\n\r\n // Watchlist sidebar (right side). Appended AFTER the chart container so\r\n // it sits to the right of the canvas in the flexbox row.\r\n if (options.watchlist) {\r\n this.watchlist = new WidgetWatchlist(body, this.symbols, {\r\n onSelect: (sym) => { void this.setSymbol(sym); },\r\n });\r\n this.watchlist.setActive(this.state.symbol);\r\n }\r\n\r\n this.root.appendChild(body);\r\n\r\n // 5. Create chart\r\n this.chart = new Chart(this.chartContainer, {\r\n chartType: this.state.chartType,\r\n theme: resolvedTheme,\r\n autoScale: true,\r\n crosshair: { mode: 'magnet' },\r\n features: {\r\n drawings: true,\r\n drawingMagnet: true,\r\n drawingUndoRedo: true,\r\n indicators: true,\r\n trading: options.trading !== false,\r\n tradingContextMenu: options.trading !== false,\r\n volume: true,\r\n legend: true,\r\n crosshair: true,\r\n keyboard: true,\r\n screenshot: true,\r\n alerts: true,\r\n barCountdown: true,\r\n logScale: true,\r\n watermark: true,\r\n },\r\n ...options.chartOptions,\r\n });\r\n\r\n // Drag-and-drop CSV / JSON onto the chart container — instant data load.\r\n // Opt-out via `dragDropImport: false`. The adapter (live stream) keeps\r\n // running but the next bar update will append to whatever we just\r\n // loaded — that's the expected behavior when overlaying historical data.\r\n if (options.dragDropImport !== false) {\r\n this.dragDrop = new DragDropImporter(this.chartContainer, {\r\n onData: (data, result, file) => {\r\n this.setData(data);\r\n this.toast(`Loaded ${result.data.length} bars from ${file.name}` + (result.skipped > 0 ? ` (${result.skipped} skipped)` : ''));\r\n },\r\n onError: (err, file) => {\r\n this.toast(`${file.name}: ${err.message}`, 'error');\r\n },\r\n });\r\n this.dragDrop.attach();\r\n }\r\n\r\n // 6. Create status bar\r\n if (options.statusBar !== false) {\r\n this.statusBar = new WidgetStatusBar(this.root);\r\n }\r\n\r\n // 7. Create settings (lazy, not appended until opened)\r\n if (options.settings !== false) {\r\n this.settings = new WidgetSettings({\r\n onChange: (patch) => this.applySettings(patch),\r\n onReset: () => this.resetSettings(),\r\n onClose: () => {},\r\n });\r\n }\r\n\r\n // 8a. Symbol search\r\n this.symbolSearch = new WidgetSymbolSearch({\r\n onPick: (sym) => { void this.setSymbol(sym); },\r\n onClose: () => {},\r\n });\r\n this.hotkeySheet = new WidgetHotkeySheet({ onClose: () => {} });\r\n\r\n // Replay: click a revealed bar to jump the replay cursor there.\r\n this.chart.on('barClick', (e) => {\r\n if (!this.replayBar?.isMounted()) return;\r\n const idx = (e.payload as { barIndex?: number }).barIndex;\r\n if (typeof idx !== 'number') return;\r\n if (this.chart.getReplayState() === 'playing') this.chart.replayPause();\r\n this.chart.replaySeek(idx);\r\n this.replayBar.setState('paused');\r\n });\r\n\r\n // Data Window — precise OHLCV + indicator values at the hovered bar.\r\n this.dataWindow = new WidgetDataWindow(this.root, { formatPrice: (p) => this.formatAlertPrice(p) });\r\n this.chart.on('crosshairMove', (e) => {\r\n const p = e.payload as { barIndex?: number };\r\n this.lastHoverIndex = typeof p.barIndex === 'number' ? p.barIndex : null;\r\n if (this.dataWindow?.isOpen()) this.dataWindow.render(this.buildDataWindowModel());\r\n });\r\n\r\n // Drawing style + templates popover (paired with the sidebar palette button)\r\n if (options.drawingTools !== false) {\r\n this.drawingStyle = new WidgetDrawingStyle(\r\n this.root,\r\n {\r\n onStyleChange: (style) => {\r\n this.chart.setDrawingStyle(style);\r\n this.chart.setSelectedDrawingStyle(style);\r\n },\r\n getStyle: () => this.chart.getDrawingStyle(),\r\n },\r\n new DrawingTemplateStore(),\r\n );\r\n }\r\n\r\n // Bracket-order placement: floating confirm/cancel bar + event wiring.\r\n if (options.trading !== false) {\r\n this.bracketBar = new WidgetBracketBar(this.root, {\r\n onConfirm: () => this.chart.confirmBracket(),\r\n onCancel: () => {\r\n this.chart.cancelBracket();\r\n this.bracketBar?.hide();\r\n },\r\n });\r\n this.chart.on('bracketPlace', (e) => {\r\n const b = e.payload;\r\n this.bracketBar?.hide();\r\n this.toast(`${b.side === 'buy' ? 'Long' : 'Short'} bracket placed · ${b.riskReward.toFixed(2)}R`);\r\n });\r\n\r\n // Depth-of-market ladder (opt-in; fed via widget.setDepth)\r\n if (options.depthLadder) {\r\n this.depthLadder = new WidgetDepthLadder(this.root, {\r\n onTrade: (side, price) => {\r\n this.chart.placeOrderIntent({ side, type: 'limit', price });\r\n this.toast(`${side === 'buy' ? 'Buy' : 'Sell'} limit @ ${this.formatAlertPrice(price)}`);\r\n },\r\n formatPrice: (p) => this.formatAlertPrice(p),\r\n });\r\n }\r\n // Esc-cancel originates in the chart; reflect it in the bar.\r\n this.chart.on('dataUpdate', (e) => {\r\n const p = e.payload as { bracket?: string };\r\n if (p && p.bracket === 'cancelled') this.bracketBar?.hide();\r\n });\r\n }\r\n\r\n // 8a-bis. Price alerts panel (floating popover, toggled from the bell button)\r\n if (options.alerts !== false) {\r\n this.alertsPanel = new WidgetAlertsPanel(this.root, {\r\n onAdd: (price, condition, message, channel, label) => {\r\n this.chart.addAlert(price, condition, message, channel, label);\r\n },\r\n onRemove: (id) => this.chart.removeAlert(id),\r\n onClear: () => this.chart.clearAlerts(),\r\n getChannelValue: (channel) => this.getAlertChannelValue(channel),\r\n formatPrice: (p) => this.formatAlertPrice(p),\r\n });\r\n\r\n // Keep the panel list and toasts in sync with the chart's AlertManager.\r\n this.chart.on('alertAdd', () => this.refreshAlerts());\r\n this.chart.on('alertRemove', () => this.refreshAlerts());\r\n this.chart.on('alertUpdate', () => this.refreshAlerts());\r\n if (options.alertNotifications) {\r\n this.alertNotifier = new AlertNotifier(options.alertNotifications);\r\n }\r\n this.chart.on('alertTriggered', (e) => {\r\n const p = e.payload;\r\n const text = `Price ${this.formatAlertPrice(p.price)}${p.message ? ` — ${p.message}` : ''}`;\r\n this.toast(`🔔 Alert: ${text}`, 'info');\r\n this.alertNotifier?.notify(text);\r\n this.refreshAlerts();\r\n });\r\n }\r\n\r\n // 8a-ter. Object tree (indicators + drawings manager)\r\n if (options.objectTree !== false) {\r\n this.indicatorSettings = new WidgetIndicatorSettings(this.root, {\r\n onApply: (instanceId, params) => this.chart.updateIndicator(instanceId, params),\r\n onClose: () => {},\r\n });\r\n this.objectTree = new WidgetObjectTree(this.root, {\r\n onRemoveIndicator: (iid) => this.handleRemoveIndicator(iid),\r\n onConfigureIndicator: (iid) => this.openIndicatorSettings(iid),\r\n onToggleIndicatorVisible: (iid, visible) => {\r\n this.chart.setIndicatorVisible(iid, visible);\r\n this.refreshObjects();\r\n },\r\n onRemoveDrawing: (id) => {\r\n this.chart.removeDrawing(id);\r\n this.refreshObjects();\r\n },\r\n onToggleDrawingVisible: (id, visible) => {\r\n this.chart.setDrawingVisible(id, visible);\r\n this.refreshObjects();\r\n },\r\n onToggleDrawingLocked: (id, locked) => {\r\n this.chart.setDrawingLocked(id, locked);\r\n this.refreshObjects();\r\n },\r\n onAddCompare: () => this.handleAddCompare(),\r\n onRemoveCompare: (id) => this.handleRemoveCompare(id),\r\n });\r\n const refresh = () => { if (this.objectTree?.isOpen()) this.refreshObjects(); };\r\n this.chart.on('drawingCreate', refresh);\r\n this.chart.on('drawingRemove', refresh);\r\n this.chart.on('indicatorAdd', refresh);\r\n this.chart.on('indicatorRemove', refresh);\r\n }\r\n\r\n // 8b. Command palette\r\n this.commandPalette = new WidgetCommandPalette({\r\n onIndicator: (id) => this.handleAddIndicator(id),\r\n onChartType: (type) => this.handleChartType(type),\r\n onDrawingTool: (tool) => this.handleDrawingTool(tool),\r\n onTimeframe: (tf) => this.handleTimeframe(tf),\r\n onAction: (id) => this.handleAction(id),\r\n onClose: () => {},\r\n });\r\n\r\n this.boundGlobalKeydown = (e: KeyboardEvent) => {\r\n if ((e.ctrlKey || e.metaKey) && e.key === 'k') {\r\n e.preventDefault();\r\n this.toggleCommandPalette();\r\n } else if ((e.ctrlKey || e.metaKey) && (e.key === 'p' || e.key === 'P')) {\r\n // Ctrl/Cmd+P → symbol search (matches Bloomberg / many trading UIs)\r\n e.preventDefault();\r\n this.symbolSearch?.open(this.symbols, this.state.symbol);\r\n } else if (e.key === '?' && !e.ctrlKey && !e.metaKey && !e.altKey) {\r\n // Only fire when the user isn't typing into an input.\r\n const active = document.activeElement as HTMLElement | null;\r\n if (active && (active.tagName === 'INPUT' || active.tagName === 'TEXTAREA' || active.isContentEditable)) return;\r\n e.preventDefault();\r\n this.hotkeySheet?.open();\r\n }\r\n };\r\n document.addEventListener('keydown', this.boundGlobalKeydown);\r\n\r\n // 9. Connect stream\r\n if (options.adapter) {\r\n this.adapter = options.adapter;\r\n this.connectStream();\r\n }\r\n\r\n // Watchlist live-update loop. 1s cadence keeps DOM churn low while still\r\n // feeling responsive; for sub-second visual response, apps can call\r\n // `setWatchlistEntry` directly from their own WebSocket.\r\n if (this.watchlist) {\r\n this.watchlistInterval = setInterval(() => this.tickWatchlist(), 1000);\r\n }\r\n\r\n // Initial UI update\r\n this.updateUI();\r\n\r\n // 9. Fire onReady\r\n options.onReady?.(this.chart);\r\n\r\n // Deep-link restore: apply a `#tcw=` view from the URL when enabled.\r\n if (options.shareUrl && typeof location !== 'undefined') {\r\n const encoded = readShareHash(location.hash);\r\n if (encoded) void this.importState(encoded);\r\n }\r\n }\r\n\r\n // --- Public API ---\r\n\r\n /** Replace the searchable symbol catalog. Does not change the active symbol. */\r\n setSymbols(symbols: string[]): void {\r\n this.symbols = symbols;\r\n this.watchlist?.setSymbols(symbols);\r\n }\r\n\r\n async setSymbol(symbol: string): Promise<void> {\r\n // Flush the outgoing symbol's layout BEFORE switching state, so the\r\n // saved snapshot reflects what the user actually saw under that ticker.\r\n this.flushActiveLayout();\r\n this.state = { ...this.state, symbol };\r\n this.sessionRefPrice = null;\r\n this.options.onSymbolChange?.(symbol);\r\n this.updateUI();\r\n this.watchlist?.setActive(symbol);\r\n if (this.adapter) {\r\n await this.connectStream();\r\n }\r\n }\r\n\r\n /**\r\n * Push an entry into the watchlist (e.g., from your own WebSocket).\r\n * Call with the symbols you care about; the active symbol is updated\r\n * automatically from the chart's live data.\r\n */\r\n setWatchlistEntry(symbol: string, entry: Partial<WatchlistEntry>): void {\r\n this.watchlist?.setEntry(symbol, entry);\r\n }\r\n\r\n private tickWatchlist(): void {\r\n if (!this.watchlist) return;\r\n const data = this.chart.getData();\r\n if (data.length === 0) return;\r\n const last = data[data.length - 1];\r\n // Reference price: first bar of the loaded slice — that's the closest\r\n // approximation of \"session open\" without timezone bookkeeping. Apps\r\n // that need true session-open can override via `setWatchlistEntry`.\r\n if (this.sessionRefPrice === null) {\r\n this.sessionRefPrice = data[0].open;\r\n }\r\n\r\n const buf = this.watchlistSparkBuffer.get(this.state.symbol) ?? [];\r\n buf.push(last.close);\r\n if (buf.length > 40) buf.shift();\r\n this.watchlistSparkBuffer.set(this.state.symbol, buf);\r\n\r\n this.watchlist.setEntry(this.state.symbol, {\r\n lastPrice: last.close,\r\n refPrice: this.sessionRefPrice,\r\n sparkline: buf.slice(),\r\n });\r\n }\r\n\r\n async setTimeframe(tf: TimeFrame): Promise<void> {\r\n this.state = { ...this.state, timeframe: tf };\r\n this.options.onTimeframeChange?.(tf);\r\n this.updateUI();\r\n if (this.adapter) {\r\n await this.connectStream();\r\n return;\r\n }\r\n if (this.options.resampleTimeframes !== false) {\r\n this.applyTimeframeData();\r\n }\r\n }\r\n\r\n setTheme(theme: import('@tradecanvas/commons').ThemeName | Theme): void {\r\n const isDark = this.resolveIsDark(theme);\r\n const resolved = this.resolveTheme(theme);\r\n this.state = { ...this.state, isDark };\r\n this.root.dataset.tcwTheme = isDark ? 'dark' : 'light';\r\n this.chart.setTheme(resolved);\r\n this.updateUI();\r\n }\r\n\r\n getChart(): Chart {\r\n return this.chart;\r\n }\r\n\r\n destroy(): void {\r\n if (this.destroyed) return;\r\n this.destroyed = true;\r\n\r\n if (this.boundGlobalKeydown) {\r\n document.removeEventListener('keydown', this.boundGlobalKeydown);\r\n }\r\n this.flushActiveLayout();\r\n this.commandPalette?.destroy();\r\n this.symbolSearch?.destroy();\r\n this.hotkeySheet?.destroy();\r\n if (this.replayPollInterval) clearInterval(this.replayPollInterval);\r\n this.replayBar?.destroy();\r\n this.dragDrop?.detach();\r\n this.alertsPanel?.destroy();\r\n this.objectTree?.destroy();\r\n this.indicatorSettings?.destroy();\r\n this.drawingStyle?.destroy();\r\n this.bracketBar?.destroy();\r\n this.alertNotifier?.destroy();\r\n this.depthLadder?.destroy();\r\n this.dataWindow?.destroy();\r\n if (this.watchlistInterval) clearInterval(this.watchlistInterval);\r\n this.watchlist?.destroy();\r\n this.toolbar?.destroy();\r\n this.sidebar?.destroy();\r\n this.settings?.destroy();\r\n this.statusBar?.destroy();\r\n this.chart.destroy();\r\n this.root.remove();\r\n removeWidgetStyles();\r\n }\r\n\r\n // --- Internal handlers ---\r\n\r\n private handleSymbolClick(): void {\r\n // Opens the fuzzy search modal. The cycle-through behaviour the toolbar\r\n // used to do is gone — a real search scales past 3-4 symbols and matches\r\n // user expectations from TradingView, Bloomberg, etc.\r\n this.symbolSearch?.open(this.symbols, this.state.symbol);\r\n }\r\n\r\n private handleTimeframe(tf: TimeFrame): void {\r\n this.state = { ...this.state, timeframe: tf };\r\n this.options.onTimeframeChange?.(tf);\r\n this.updateUI();\r\n if (this.adapter) {\r\n // Live adapter owns the data — refetch at the native resolution.\r\n this.connectStream();\r\n return;\r\n }\r\n if (this.options.resampleTimeframes === false) return;\r\n // Static data: aggregate the base series locally. Lazily adopt whatever is\r\n // currently on the chart as the base if the host fed it via getChart().\r\n if (!this.baseSeries) {\r\n const current = this.chart.getData();\r\n if (current.length > 0) {\r\n this.baseSeries = current;\r\n this.baseTimeframeMs = inferTimeframeMs(current);\r\n }\r\n }\r\n this.applyTimeframeData();\r\n }\r\n\r\n /**\r\n * Load the widget's base series. Prefer this over `getChart().setData()` so\r\n * client-side timeframe resampling has a finest-resolution source to\r\n * aggregate from. The data is rendered at the current timeframe (resampled\r\n * when that timeframe is coarser than the data's native spacing).\r\n */\r\n setData(data: DataSeries): void {\r\n this.baseSeries = data;\r\n this.baseTimeframeMs = inferTimeframeMs(data);\r\n this.applyTimeframeData();\r\n }\r\n\r\n /** Render the base series at the active timeframe, resampling when coarser. */\r\n private applyTimeframeData(): void {\r\n if (!this.baseSeries) return;\r\n const targetMs = timeframeToMs(this.state.timeframe);\r\n if (this.baseTimeframeMs > 0 && targetMs > this.baseTimeframeMs) {\r\n const weekStartsOn = this.options.weekStartsOn ?? 1;\r\n this.chart.setData(resampleOHLCV(this.baseSeries, this.state.timeframe, { weekStartsOn }));\r\n } else {\r\n this.chart.setData(this.baseSeries);\r\n }\r\n }\r\n\r\n private toggleAlerts(): void {\r\n if (!this.alertsPanel) return;\r\n this.alertsPanel.toggle();\r\n if (this.alertsPanel.isOpen()) this.refreshAlerts();\r\n }\r\n\r\n private handleToggleFavorite(tool: DrawingToolType): void {\r\n const pinned = this.favoritesStore.toggle(tool);\r\n this.sidebar?.setFavorites(this.favoritesStore.list());\r\n this.toast(pinned ? 'Pinned to favorites' : 'Unpinned');\r\n }\r\n\r\n /** Encode the current view (symbol, timeframe, chart type, scale, indicators, drawings). */\r\n exportState(): string {\r\n const indicators = this.chart.getActiveIndicators().map((i) => ({\r\n id: i.id,\r\n params: i.params as Record<string, number | string | boolean>,\r\n }));\r\n return encodeWidgetState({\r\n v: 1,\r\n symbol: this.state.symbol,\r\n timeframe: this.state.timeframe,\r\n chartType: this.state.chartType,\r\n scaleMode: this.chart.getScaleMode(),\r\n indicators,\r\n drawings: this.chart.getDrawings(),\r\n });\r\n }\r\n\r\n /** Restore a view from an `exportState()` string. Returns false if malformed. */\r\n async importState(encoded: string): Promise<boolean> {\r\n const s = decodeWidgetState(encoded);\r\n if (!s) return false;\r\n\r\n // Symbol/timeframe first so any stream/layout restore happens before we\r\n // overlay the shared view on top.\r\n if (s.symbol && s.symbol !== this.state.symbol) await this.setSymbol(s.symbol);\r\n if (s.timeframe && s.timeframe !== this.state.timeframe) await this.setTimeframe(s.timeframe);\r\n\r\n if (s.chartType) this.handleChartType(s.chartType);\r\n this.chart.setScaleMode(s.scaleMode);\r\n\r\n for (const [, instanceId] of this.state.activeIndicators) this.chart.removeIndicator(instanceId);\r\n const map = new Map<string, string>();\r\n for (const ind of s.indicators) {\r\n const iid = this.chart.addIndicator(ind.id, ind.params);\r\n if (iid) map.set(ind.id, iid);\r\n }\r\n this.state = { ...this.state, activeIndicators: map };\r\n this.chart.setDrawings(s.drawings);\r\n this.updateUI();\r\n return true;\r\n }\r\n\r\n /** Copy the chart image to the clipboard, with a toast on success/failure. */\r\n async copyChartImage(): Promise<void> {\r\n const ok = await this.chart.copyScreenshot();\r\n this.toast(ok ? 'Chart image copied' : 'Copy failed — image clipboard unavailable', ok ? 'info' : 'error');\r\n }\r\n\r\n /** Copy a shareable deep-link (current view encoded in the URL hash) to the clipboard. */\r\n async copyShareLink(): Promise<void> {\r\n const base = typeof location !== 'undefined' ? location.href : '';\r\n const url = buildShareUrl(base, this.exportState());\r\n try {\r\n await navigator.clipboard.writeText(url);\r\n this.toast('Share link copied');\r\n } catch {\r\n this.toast('Copy failed — clipboard unavailable', 'error');\r\n }\r\n }\r\n\r\n /** Feed order-book depth to the chart overlay, depth ladder, and heatmap. */\r\n setDepth(depth: DepthData | null): void {\r\n this.chart.setDepthData(depth);\r\n this.depthLadder?.setData(depth);\r\n if (depth) this.chart.pushDepthSnapshot(depth);\r\n }\r\n\r\n /** Begin a draggable bracket order at the latest price and show the action bar. */\r\n startBracket(side: 'buy' | 'sell'): void {\r\n if (this.chart.startBracket(side)) {\r\n this.bracketBar?.show(side);\r\n }\r\n }\r\n\r\n private buildDataWindowModel(): DataWindowModel {\r\n const data = this.chart.getData();\r\n const idx = this.lastHoverIndex;\r\n if (idx === null || idx < 0 || idx >= data.length) {\r\n return { ohlc: null, change: 0, changePct: 0, indicators: [] };\r\n }\r\n const bar = data[idx];\r\n const prevClose = idx > 0 ? data[idx - 1].close : bar.open;\r\n const change = bar.close - prevClose;\r\n const changePct = prevClose !== 0 ? (change / prevClose) * 100 : 0;\r\n\r\n const indicators = this.chart.getActiveIndicators().map((ind) => {\r\n const series = this.chart.getIndicatorOutput(ind.instanceId)?.series;\r\n const point = series?.[idx] ?? null;\r\n const values = point\r\n ? Object.entries(point)\r\n .filter(([, v]) => typeof v === 'number' && Number.isFinite(v))\r\n .map(([key, v]) => ({ key, value: v as number }))\r\n : [];\r\n return { name: ind.descriptor.name, values };\r\n }).filter((i) => i.values.length > 0);\r\n\r\n return {\r\n ohlc: { open: bar.open, high: bar.high, low: bar.low, close: bar.close, volume: bar.volume },\r\n change,\r\n changePct,\r\n indicators,\r\n };\r\n }\r\n\r\n private toggleDataWindow(): void {\r\n if (!this.dataWindow) return;\r\n this.dataWindow.toggle();\r\n if (this.dataWindow.isOpen()) this.dataWindow.render(this.buildDataWindowModel());\r\n }\r\n\r\n private toggleObjects(): void {\r\n if (!this.objectTree) return;\r\n this.objectTree.toggle();\r\n if (this.objectTree.isOpen()) this.refreshObjects();\r\n }\r\n\r\n private openIndicatorSettings(instanceId: string): void {\r\n if (!this.indicatorSettings) return;\r\n const ind = this.chart.getActiveIndicators().find((i) => i.instanceId === instanceId);\r\n if (!ind) return;\r\n this.indicatorSettings.open({\r\n instanceId,\r\n name: ind.descriptor.name,\r\n defaults: ind.descriptor.defaultConfig,\r\n params: ind.params,\r\n });\r\n }\r\n\r\n private refreshObjects(): void {\r\n if (!this.objectTree) return;\r\n const indicators = this.chart.getActiveIndicators().map((i) => ({\r\n instanceId: i.instanceId,\r\n name: i.descriptor.name,\r\n visible: i.visible,\r\n }));\r\n const drawings = this.chart.getDrawings().map((d) => ({\r\n id: d.id,\r\n label: drawingTypeLabel(d.type),\r\n visible: d.visible,\r\n locked: d.locked,\r\n }));\r\n const compares = this.compares.map((c) => ({ id: c.id, label: c.symbol, color: c.color }));\r\n this.objectTree.setObjects(indicators, drawings, compares);\r\n }\r\n\r\n private async handleAddCompare(): Promise<void> {\r\n if (!this.adapter) {\r\n this.toast('Comparison needs a live data adapter', 'error');\r\n return;\r\n }\r\n const taken = new Set([this.state.symbol, ...this.compares.map((c) => c.symbol)]);\r\n const options = this.symbols.filter((s) => !taken.has(s));\r\n this.symbolSearch?.open(options.length ? options : this.symbols, this.state.symbol, (symbol) => {\r\n void this.addCompareSymbol(symbol);\r\n });\r\n }\r\n\r\n /** Overlay another symbol's normalized series. Fetches history via the adapter. */\r\n async addCompareSymbol(symbol: string): Promise<void> {\r\n if (!this.adapter || this.compares.some((c) => c.symbol === symbol)) return;\r\n const color = COMPARE_COLORS[this.compares.length % COMPARE_COLORS.length];\r\n const id = `cmp_${symbol}`;\r\n try {\r\n const bars = await this.adapter.fetchHistory(symbol, this.state.timeframe, this.options.historyLimit ?? 500);\r\n // Percent mode normalizes mixed-price symbols (e.g. BTC vs a $2 alt) onto\r\n // a shared % axis — the right default for comparison.\r\n if (this.compares.length === 0) this.chart.setCompareMode('percent');\r\n this.chart.addCompareSymbol(id, symbol, bars, color);\r\n this.compares = [...this.compares, { id, symbol, color }];\r\n this.refreshObjects();\r\n this.toast(`Comparing ${symbol}`);\r\n } catch (err: unknown) {\r\n this.toast(`${symbol}: ${err instanceof Error ? err.message : 'failed to load'}`, 'error');\r\n }\r\n }\r\n\r\n private handleRemoveCompare(id: string): void {\r\n this.chart.removeCompareSymbol(id);\r\n this.compares = this.compares.filter((c) => c.id !== id);\r\n this.refreshObjects();\r\n }\r\n\r\n /** Refetch every comparison overlay at the current symbol/timeframe. */\r\n private async refetchCompares(): Promise<void> {\r\n if (!this.adapter || this.compares.length === 0) return;\r\n // A comparison against the now-active symbol is redundant — drop it.\r\n const stale = this.compares.filter((c) => c.symbol === this.state.symbol);\r\n for (const c of stale) this.handleRemoveCompare(c.id);\r\n\r\n for (const c of this.compares) {\r\n try {\r\n const bars = await this.adapter.fetchHistory(c.symbol, this.state.timeframe, this.options.historyLimit ?? 500);\r\n this.chart.updateCompareData(c.id, bars);\r\n } catch { /* leave the stale overlay in place if the refetch fails */ }\r\n }\r\n }\r\n\r\n private refreshAlerts(): void {\r\n if (!this.alertsPanel) return;\r\n this.alertsPanel.setSources(this.buildAlertSources());\r\n this.alertsPanel.setAlerts(\r\n this.chart.getAlerts().map((a) => ({\r\n id: a.id,\r\n price: a.price,\r\n condition: a.condition,\r\n message: a.message,\r\n triggered: a.triggered,\r\n channel: a.channel,\r\n label: a.label,\r\n })),\r\n );\r\n }\r\n\r\n /** Price + every active indicator line, as selectable alert sources. */\r\n private buildAlertSources(): { channel: string; label: string }[] {\r\n const sources = [{ channel: 'price', label: 'Price' }];\r\n for (const ind of this.chart.getActiveIndicators()) {\r\n // Use the latest point — multi-output indicators (MACD, Stochastic) only\r\n // have all their lines populated once warmed up; the first point may not.\r\n const series = this.chart.getIndicatorOutput(ind.instanceId)?.series;\r\n const point = series && series.length > 0 ? series[series.length - 1] : null;\r\n const keys = point ? Object.keys(point).filter((k) => typeof point[k] === 'number') : [];\r\n for (const key of keys) {\r\n const label = keys.length > 1 ? `${ind.descriptor.name} ${key}` : ind.descriptor.name;\r\n sources.push({ channel: `${ind.instanceId}:${key}`, label });\r\n }\r\n }\r\n return sources;\r\n }\r\n\r\n /** Latest value for an alert source channel (price or indicator line). */\r\n private getAlertChannelValue(channel: string): number | null {\r\n const data = this.chart.getData();\r\n if (channel === 'price') return data.length > 0 ? data[data.length - 1].close : null;\r\n const sep = channel.indexOf(':');\r\n if (sep < 0 || data.length === 0) return null;\r\n const instanceId = channel.slice(0, sep);\r\n const key = channel.slice(sep + 1);\r\n const v = this.chart.getIndicatorOutput(instanceId)?.series?.[data.length - 1]?.[key];\r\n return typeof v === 'number' && Number.isFinite(v) ? v : null;\r\n }\r\n\r\n private formatAlertPrice(price: number): string {\r\n // No fixed precision config on the widget — pick digits from magnitude so\r\n // BTC (64,200.5) and a sub-dollar alt (0.04821) both read sensibly.\r\n const abs = Math.abs(price);\r\n const digits = abs >= 1000 ? 2 : abs >= 1 ? 4 : 6;\r\n const locale = this.settingsState.numberLocale || undefined;\r\n return price.toLocaleString(locale, { minimumFractionDigits: 2, maximumFractionDigits: digits });\r\n }\r\n\r\n private handleChartType(type: ChartType): void {\r\n this.state = { ...this.state, chartType: type };\r\n this.chart.setChartType(type);\r\n this.updateUI();\r\n }\r\n\r\n private handleAddIndicator(indId: string): void {\r\n if (this.state.activeIndicators.has(indId)) {\r\n // Toggle off\r\n const instanceId = this.state.activeIndicators.get(indId)!;\r\n this.chart.removeIndicator(instanceId);\r\n const next = new Map(this.state.activeIndicators);\r\n next.delete(indId);\r\n this.state = { ...this.state, activeIndicators: next };\r\n } else {\r\n const instanceId = this.chart.addIndicator(indId);\r\n if (instanceId) {\r\n const next = new Map(this.state.activeIndicators);\r\n next.set(indId, instanceId);\r\n this.state = { ...this.state, activeIndicators: next };\r\n }\r\n }\r\n this.updateUI();\r\n }\r\n\r\n private handleRemoveIndicator(instanceId: string): void {\r\n this.chart.removeIndicator(instanceId);\r\n const next = new Map(this.state.activeIndicators);\r\n for (const [id, iid] of next.entries()) {\r\n if (iid === instanceId) {\r\n next.delete(id);\r\n break;\r\n }\r\n }\r\n this.state = { ...this.state, activeIndicators: next };\r\n this.updateUI();\r\n }\r\n\r\n private toggleCommandPalette(): void {\r\n if (this.commandPalette?.isOpen()) {\r\n this.commandPalette.close();\r\n return;\r\n }\r\n this.commandPalette?.open(this.buildCommandItems());\r\n }\r\n\r\n private buildCommandItems(): CommandItem[] {\r\n const items: CommandItem[] = [];\r\n\r\n for (const ind of INDICATORS) {\r\n items.push({\r\n id: ind.id,\r\n label: ind.name,\r\n category: 'indicator',\r\n active: this.state.activeIndicators.has(ind.id),\r\n });\r\n }\r\n\r\n for (const ct of CHART_TYPES) {\r\n items.push({\r\n id: ct.value,\r\n label: ct.label,\r\n category: 'chartType',\r\n active: this.state.chartType === ct.value,\r\n });\r\n }\r\n\r\n for (const group of DRAWING_TOOL_GROUPS) {\r\n for (const tool of group.tools) {\r\n items.push({\r\n id: tool.value,\r\n label: tool.label,\r\n category: 'drawing',\r\n active: this.state.activeTool === tool.value,\r\n });\r\n }\r\n }\r\n\r\n for (const tf of TIMEFRAMES) {\r\n items.push({\r\n id: tf.value,\r\n label: tf.label,\r\n category: 'timeframe',\r\n active: this.state.timeframe === tf.value,\r\n });\r\n }\r\n\r\n items.push(\r\n { id: 'screenshot', label: 'Screenshot', category: 'action', shortcut: '' },\r\n { id: 'copyImage', label: 'Copy Chart Image', category: 'action' },\r\n { id: 'toggleTheme', label: 'Toggle Theme', category: 'action' },\r\n { id: 'settings', label: 'Settings', category: 'action' },\r\n { id: 'shareView', label: 'Share View (copy link)', category: 'action' },\r\n { id: 'autoFib', label: 'Auto Fibonacci (visible swing)', category: 'action' },\r\n { id: 'dataWindow', label: 'Toggle Data Window', category: 'action' },\r\n { id: 'clearDrawings', label: 'Clear All Drawings', category: 'action' },\r\n );\r\n\r\n return items;\r\n }\r\n\r\n private handleAction(id: string): void {\r\n switch (id) {\r\n case 'screenshot':\r\n this.chart.screenshot();\r\n break;\r\n case 'toggleTheme':\r\n this.handleToggleTheme();\r\n break;\r\n case 'settings':\r\n this.openSettings();\r\n break;\r\n case 'copyImage':\r\n void this.copyChartImage();\r\n break;\r\n case 'shareView':\r\n void this.copyShareLink();\r\n break;\r\n case 'autoFib': {\r\n const id = this.chart.autoFib();\r\n this.toast(id ? 'Auto Fibonacci added' : 'No clear swing in view');\r\n break;\r\n }\r\n case 'dataWindow':\r\n this.toggleDataWindow();\r\n break;\r\n case 'clearDrawings':\r\n this.chart.clearDrawings();\r\n this.state = { ...this.state, activeTool: null };\r\n this.updateUI();\r\n break;\r\n }\r\n }\r\n\r\n private handleDrawingTool(tool: DrawingToolType): void {\r\n this.state = { ...this.state, activeTool: tool };\r\n this.chart.setDrawingTool(tool);\r\n this.updateUI();\r\n }\r\n\r\n private handleCancelDrawing(): void {\r\n this.state = { ...this.state, activeTool: null };\r\n this.chart.setDrawingTool(null);\r\n this.updateUI();\r\n }\r\n\r\n private handleToggleMagnet(): void {\r\n const magnetEnabled = !this.state.magnetEnabled;\r\n this.state = { ...this.state, magnetEnabled };\r\n this.chart.setDrawingMagnet(magnetEnabled);\r\n this.updateUI();\r\n }\r\n\r\n private handleToggleTheme(): void {\r\n const isDark = !this.state.isDark;\r\n this.state = { ...this.state, isDark };\r\n this.root.dataset.tcwTheme = isDark ? 'dark' : 'light';\r\n this.chart.setTheme(isDark ? DARK_THEME : LIGHT_THEME);\r\n this.chart.setWatermark(this.state.symbol.replace('USDT', ' / USDT'), {\r\n fontSize: 48,\r\n color: isDark ? 'rgba(255,255,255,0.03)' : 'rgba(0,0,0,0.03)',\r\n });\r\n this.updateUI();\r\n }\r\n\r\n private openSettings(): void {\r\n this.settings?.open(this.settingsState);\r\n }\r\n\r\n // --- Toast ---\r\n\r\n /**\r\n * Show a transient toast inside the widget. Auto-dismisses after 3.5s.\r\n * Used by the drag-drop importer for success / failure feedback, but\r\n * exposed so apps can post their own (e.g. \"alert triggered at 64,200\").\r\n */\r\n toast(message: string, kind: 'info' | 'error' = 'info'): void {\r\n const el = document.createElement('div');\r\n el.className = `tcw-toast ${kind === 'error' ? 'tcw-toast-error' : ''}`;\r\n el.textContent = message;\r\n this.root.appendChild(el);\r\n // Trigger CSS transition on next frame\r\n requestAnimationFrame(() => el.classList.add('tcw-toast-in'));\r\n setTimeout(() => {\r\n el.classList.remove('tcw-toast-in');\r\n el.addEventListener('transitionend', () => el.remove(), { once: true });\r\n // Hard timeout in case transitionend doesn't fire (display:none, etc.)\r\n setTimeout(() => el.remove(), 400);\r\n }, 3500);\r\n }\r\n\r\n // --- Layout persistence ---\r\n\r\n /**\r\n * Wipe the layout saved for `symbol` (or the active symbol if omitted).\r\n * Useful as an \"Reset layout\" command in user-facing menus.\r\n */\r\n clearSavedLayout(symbol?: string): void {\r\n if (!this.layoutKeyPrefix) return;\r\n const target = symbol ?? this.state.symbol;\r\n try {\r\n localStorage.removeItem(this.layoutKeyPrefix + target);\r\n } catch { /* localStorage may be unavailable (private mode, SSR, etc.) */ }\r\n }\r\n\r\n private applySymbolLayout(symbol: string): void {\r\n if (!this.layoutKeyPrefix) return;\r\n const key = this.layoutKeyPrefix + symbol;\r\n this.activeLayoutKey = key;\r\n\r\n try {\r\n // Best-effort load. If parsing or any restore step throws, we silently\r\n // fall back to a fresh layout — a corrupted layout shouldn't break the\r\n // chart.\r\n const ok = this.chart.loadStateFromStorage(key);\r\n if (ok) this.rebuildActiveIndicatorsMapFromChart();\r\n } catch { /* swallow — layout will be rebuilt from user actions */ }\r\n\r\n // Wire chart-level auto-save so any further drawing/indicator change\r\n // flushes itself into this symbol's slot.\r\n this.chart.setAutoSave(key, this.layoutDebounceMs);\r\n }\r\n\r\n private flushActiveLayout(): void {\r\n if (!this.activeLayoutKey) return;\r\n try { this.chart.saveState(this.activeLayoutKey); } catch { /* same */ }\r\n this.chart.disableAutoSave();\r\n this.activeLayoutKey = null;\r\n }\r\n\r\n /**\r\n * After loading a layout, the chart restores indicator instances but our\r\n * `state.activeIndicators` map (used to render the chip strip) is stale.\r\n * Rebuild it from the live `getActiveIndicators` list.\r\n */\r\n private rebuildActiveIndicatorsMapFromChart(): void {\r\n const next = new Map<string, string>();\r\n for (const a of this.chart.getActiveIndicators()) {\r\n next.set(a.id, a.instanceId);\r\n }\r\n this.state = { ...this.state, activeIndicators: next };\r\n this.updateUI();\r\n }\r\n\r\n // --- Replay ---\r\n\r\n private toggleReplay(): void {\r\n if (this.replayBar?.isMounted()) {\r\n this.exitReplay();\r\n } else {\r\n this.enterReplay();\r\n }\r\n }\r\n\r\n private enterReplay(): void {\r\n const data = this.chart.getData();\r\n if (data.length < 2) return;\r\n\r\n // Snapshot full series so we can restore it on exit. The chart's\r\n // dataManager gets mutated to slices during replay.\r\n this.replayOriginalData = data.slice();\r\n\r\n // Mount the scrubber bar inside the chart container so it floats above the\r\n // canvas. It owns its own absolute positioning via the .tcw-replay-bar CSS.\r\n this.replayBar = new WidgetReplayBar({\r\n onPlay: () => {\r\n if (this.chart.getReplayState() === 'paused') {\r\n this.chart.replayResume();\r\n } else {\r\n this.chart.replayStart({ speed: this.replaySpeed, interval: 200 });\r\n }\r\n this.replayBar?.setState('playing');\r\n },\r\n onPause: () => {\r\n this.chart.replayPause();\r\n this.replayBar?.setState('paused');\r\n },\r\n onStop: () => {\r\n this.chart.replayStop();\r\n this.replayBar?.setState('paused');\r\n },\r\n onStepBack: () => {\r\n const p = this.chart.getReplayProgress();\r\n if (this.chart.getReplayState() === 'playing') this.chart.replayPause();\r\n this.chart.replaySeek(Math.max(0, p.current - 1));\r\n this.replayBar?.setState('paused');\r\n },\r\n onStepForward: () => {\r\n const p = this.chart.getReplayProgress();\r\n if (this.chart.getReplayState() === 'playing') this.chart.replayPause();\r\n this.chart.replaySeek(Math.min(p.total - 1, p.current + 1));\r\n this.replayBar?.setState('paused');\r\n },\r\n onSeek: (idx) => {\r\n if (this.chart.getReplayState() === 'playing') this.chart.replayPause();\r\n this.chart.replaySeek(idx);\r\n this.replayBar?.setState('paused');\r\n },\r\n onSpeedChange: (s) => {\r\n this.replaySpeed = s;\r\n this.chart.setReplaySpeed(s);\r\n },\r\n onClose: () => this.exitReplay(),\r\n });\r\n this.replayBar.mount(this.chartContainer, { total: data.length, speed: this.replaySpeed });\r\n\r\n // Boot replay paused at bar 1 so the user sees a starting state. Then\r\n // start polling progress for the scrubber — cheap, runs at 200ms.\r\n this.chart.replayStart({ speed: this.replaySpeed, interval: 200, startIndex: 1 });\r\n this.chart.replayPause();\r\n this.replayBar.setState('paused');\r\n\r\n this.replayPollInterval = setInterval(() => {\r\n if (!this.replayBar?.isMounted()) return;\r\n const p = this.chart.getReplayProgress();\r\n this.replayBar.setProgress(p.current, p.total);\r\n const state = this.chart.getReplayState();\r\n if (state === 'stopped') {\r\n this.replayBar.setState('paused');\r\n } else {\r\n this.replayBar.setState(state);\r\n }\r\n }, 150);\r\n }\r\n\r\n private exitReplay(): void {\r\n if (this.replayPollInterval) {\r\n clearInterval(this.replayPollInterval);\r\n this.replayPollInterval = null;\r\n }\r\n this.chart.replayStop();\r\n this.replayBar?.unmount();\r\n this.replayBar = null;\r\n if (this.replayOriginalData) {\r\n this.chart.setData(this.replayOriginalData);\r\n this.replayOriginalData = null;\r\n }\r\n }\r\n\r\n private applySettings(patch: Partial<ChartSettingsState>): void {\r\n this.settingsState = { ...this.settingsState, ...patch };\r\n\r\n if (patch.gridVisible !== undefined) this.chart.setGridVisible(patch.gridVisible);\r\n if (patch.volumeVisible !== undefined) this.chart.setVolumeVisible(patch.volumeVisible);\r\n if (patch.volumeProfileVisible !== undefined) this.chart.setVolumeProfileVisible(patch.volumeProfileVisible);\r\n if (patch.marketProfileVisible !== undefined) this.chart.setMarketProfileVisible(patch.marketProfileVisible);\r\n if (patch.marketProfileSplit !== undefined) this.chart.setMarketProfileConfig({ splitBySession: patch.marketProfileSplit });\r\n if (patch.marketProfileLetters !== undefined) this.chart.setMarketProfileConfig({ letters: patch.marketProfileLetters });\r\n if (patch.marketProfileBuckets !== undefined) this.chart.setMarketProfileConfig({ buckets: patch.marketProfileBuckets });\r\n if (patch.marketProfileOpacity !== undefined) this.chart.setMarketProfileConfig({ opacity: patch.marketProfileOpacity });\r\n if (patch.depthHeatmapVisible !== undefined) this.chart.setDepthHeatmapVisible(patch.depthHeatmapVisible);\r\n if (patch.depthHeatmapOpacity !== undefined) this.chart.setDepthHeatmapConfig({ opacity: patch.depthHeatmapOpacity });\r\n if (patch.sessionShadingVisible !== undefined) this.chart.setSessionShadingVisible(patch.sessionShadingVisible);\r\n if (patch.pivotMarkersVisible !== undefined) this.chart.setPivotMarkersVisible(patch.pivotMarkersVisible);\r\n if (patch.pivotStrength !== undefined) this.chart.setPivotMarkersConfig({ left: patch.pivotStrength, right: patch.pivotStrength });\r\n if (patch.pivotStructureLabels !== undefined) this.chart.setPivotMarkersConfig({ structureLabels: patch.pivotStructureLabels });\r\n if (patch.periodLevelsVisible !== undefined) this.chart.setPeriodLevelsVisible(patch.periodLevelsVisible);\r\n if (patch.periodLevelsPeriod !== undefined) this.chart.setPeriodLevelsPeriod(patch.periodLevelsPeriod);\r\n if (patch.crosshairMode !== undefined) this.chart.setCrosshairMode(patch.crosshairMode);\r\n if (patch.autoScale !== undefined) this.chart.setAutoScale(patch.autoScale);\r\n if (patch.scaleMode !== undefined) {\r\n this.chart.setScaleMode(patch.scaleMode);\r\n // Keep the legacy logScale flag mirrored so persisted layouts stay valid.\r\n this.settingsState = { ...this.settingsState, logScale: patch.scaleMode === 'logarithmic' };\r\n } else if (patch.logScale !== undefined) {\r\n this.chart.setLogScale(patch.logScale);\r\n this.settingsState = { ...this.settingsState, scaleMode: patch.logScale ? 'logarithmic' : 'regular' };\r\n }\r\n if (patch.numberLocale !== undefined) this.chart.setNumberLocale(patch.numberLocale);\r\n if (patch.timezone !== undefined) {\r\n this.chart.setTimezoneOffset(patch.timezone === 'local' ? null : Number(patch.timezone));\r\n }\r\n\r\n // Apply theme colors\r\n const currentTheme = this.chart.getTheme();\r\n const themeUpdate = { ...currentTheme } as Record<string, unknown>;\r\n let themeChanged = false;\r\n\r\n if (patch.candleUpColor !== undefined) { themeUpdate.candleUp = patch.candleUpColor; themeChanged = true; }\r\n if (patch.candleDownColor !== undefined) { themeUpdate.candleDown = patch.candleDownColor; themeChanged = true; }\r\n if (patch.candleUpWick !== undefined) { themeUpdate.candleUpWick = patch.candleUpWick; themeChanged = true; }\r\n if (patch.candleDownWick !== undefined) { themeUpdate.candleDownWick = patch.candleDownWick; themeChanged = true; }\r\n if (patch.backgroundColor !== undefined) { themeUpdate.background = patch.backgroundColor; themeChanged = true; }\r\n if (patch.gridColor !== undefined) { themeUpdate.grid = patch.gridColor; themeChanged = true; }\r\n\r\n if (themeChanged) {\r\n this.chart.setTheme(themeUpdate as unknown as Theme);\r\n }\r\n }\r\n\r\n private resetSettings(): void {\r\n this.settingsState = { ...DEFAULT_SETTINGS };\r\n this.applySettings(this.settingsState);\r\n }\r\n\r\n private async connectStream(): Promise<void> {\r\n if (!this.adapter) return;\r\n\r\n this.state = {\r\n ...this.state,\r\n connectionState: 'connecting',\r\n connectionMessage: 'Connecting...',\r\n };\r\n this.updateUI();\r\n\r\n try {\r\n this.chart.disconnectStream();\r\n await this.chart.connect({\r\n adapter: this.adapter,\r\n symbol: this.state.symbol,\r\n timeframe: this.state.timeframe,\r\n historyLimit: this.options.historyLimit ?? 500,\r\n });\r\n\r\n this.chart.setWatermark(this.state.symbol.replace('USDT', ' / USDT'), {\r\n fontSize: 48,\r\n color: this.state.isDark ? 'rgba(255,255,255,0.03)' : 'rgba(0,0,0,0.03)',\r\n });\r\n\r\n // Re-apply per-symbol layout (indicators, drawings, chart type) after\r\n // the new history is in. Doing this *after* connect ensures indicators\r\n // recalculate against the loaded data, not the previous symbol's data.\r\n this.applySymbolLayout(this.state.symbol);\r\n\r\n this.state = {\r\n ...this.state,\r\n connectionState: 'connected',\r\n connectionMessage: 'Live',\r\n };\r\n\r\n // Re-pull comparison overlays at the (possibly new) timeframe so they\r\n // stay aligned with the main series. Drop the active symbol if it ended\r\n // up in the compare set after a symbol switch.\r\n void this.refetchCompares();\r\n } catch (err: unknown) {\r\n this.state = {\r\n ...this.state,\r\n connectionState: 'error',\r\n connectionMessage: err instanceof Error ? err.message : 'Connection failed',\r\n };\r\n }\r\n\r\n this.updateUI();\r\n }\r\n\r\n private updateUI(): void {\r\n this.toolbar?.update(this.state);\r\n this.sidebar?.update(this.state);\r\n this.statusBar?.update({\r\n connectionState: this.state.connectionState,\r\n message: this.state.connectionMessage,\r\n symbol: this.state.symbol,\r\n timeframe: this.state.timeframe,\r\n });\r\n }\r\n\r\n private resolveIsDark(theme?: import('@tradecanvas/commons').ThemeName | Theme): boolean {\r\n if (theme === undefined || theme === 'dark') return true;\r\n if (theme === 'light') return false;\r\n // If it's a Theme object, check background color\r\n if (typeof theme === 'object' && theme.background) {\r\n return this.isColorDark(theme.background);\r\n }\r\n return true;\r\n }\r\n\r\n private resolveTheme(theme?: import('@tradecanvas/commons').ThemeName | Theme): Theme {\r\n if (theme === undefined || theme === 'dark') return DARK_THEME;\r\n if (theme === 'light') return LIGHT_THEME;\r\n if (typeof theme === 'object') return theme as Theme;\r\n return DARK_THEME;\r\n }\r\n\r\n private isColorDark(color: string): boolean {\r\n // Simple heuristic: if it starts with # and R+G+B < 384 (half of 768)\r\n if (color.startsWith('#') && color.length >= 7) {\r\n const r = parseInt(color.slice(1, 3), 16);\r\n const g = parseInt(color.slice(3, 5), 16);\r\n const b = parseInt(color.slice(5, 7), 16);\r\n return (r + g + b) < 384;\r\n }\r\n return true;\r\n }\r\n}\r\n"],"mappings":"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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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"}
|