@tradecanvas/chart 1.2.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +858 -824
  3. package/dist/Chart.d.ts +142 -2
  4. package/dist/Chart.d.ts.map +1 -1
  5. package/dist/DragDropImporter-C5kgfbET.cjs +2 -0
  6. package/dist/DragDropImporter-C5kgfbET.cjs.map +1 -0
  7. package/dist/{DragDropImporter-BcTzFeRP.js → DragDropImporter-Dd9Mud5J.js} +423 -159
  8. package/dist/DragDropImporter-Dd9Mud5J.js.map +1 -0
  9. package/dist/PaneManager.d.ts.map +1 -1
  10. package/dist/charts/ChartTypeStrategy.d.ts +6 -0
  11. package/dist/charts/ChartTypeStrategy.d.ts.map +1 -1
  12. package/dist/grid/ChartGrid.d.ts +1 -0
  13. package/dist/grid/ChartGrid.d.ts.map +1 -1
  14. package/dist/index.cjs +1 -1
  15. package/dist/index.cjs.map +1 -1
  16. package/dist/index.d.ts +5 -2
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +74 -89
  19. package/dist/index.js.map +1 -1
  20. package/dist/interaction/verticalPanGate.d.ts +22 -0
  21. package/dist/interaction/verticalPanGate.d.ts.map +1 -0
  22. package/dist/widget/ChartWidget.d.ts +71 -7
  23. package/dist/widget/ChartWidget.d.ts.map +1 -1
  24. package/dist/widget/WidgetCommandPalette.d.ts +3 -1
  25. package/dist/widget/WidgetCommandPalette.d.ts.map +1 -1
  26. package/dist/widget/WidgetDrawingSidebar.d.ts +12 -0
  27. package/dist/widget/WidgetDrawingSidebar.d.ts.map +1 -1
  28. package/dist/widget/WidgetGoToDate.d.ts +45 -0
  29. package/dist/widget/WidgetGoToDate.d.ts.map +1 -0
  30. package/dist/widget/WidgetHotkeySheet.d.ts +4 -2
  31. package/dist/widget/WidgetHotkeySheet.d.ts.map +1 -1
  32. package/dist/widget/WidgetIndicatorLegend.d.ts +68 -0
  33. package/dist/widget/WidgetIndicatorLegend.d.ts.map +1 -0
  34. package/dist/widget/WidgetLoadingOverlay.d.ts +3 -1
  35. package/dist/widget/WidgetLoadingOverlay.d.ts.map +1 -1
  36. package/dist/widget/WidgetObjectTree.d.ts +1 -1
  37. package/dist/widget/WidgetReplayBar.d.ts +37 -7
  38. package/dist/widget/WidgetReplayBar.d.ts.map +1 -1
  39. package/dist/widget/WidgetSettings.d.ts +13 -1
  40. package/dist/widget/WidgetSettings.d.ts.map +1 -1
  41. package/dist/widget/WidgetStatusBar.d.ts +16 -1
  42. package/dist/widget/WidgetStatusBar.d.ts.map +1 -1
  43. package/dist/widget/WidgetSymbolSearch.d.ts +3 -1
  44. package/dist/widget/WidgetSymbolSearch.d.ts.map +1 -1
  45. package/dist/widget/WidgetToolbar.d.ts +12 -3
  46. package/dist/widget/WidgetToolbar.d.ts.map +1 -1
  47. package/dist/widget/WidgetTooltip.d.ts +43 -0
  48. package/dist/widget/WidgetTooltip.d.ts.map +1 -0
  49. package/dist/widget/escapeHtml.d.ts +3 -0
  50. package/dist/widget/escapeHtml.d.ts.map +1 -0
  51. package/dist/widget/i18n.d.ts +26 -0
  52. package/dist/widget/i18n.d.ts.map +1 -1
  53. package/dist/widget/iconSet.d.ts +26 -0
  54. package/dist/widget/iconSet.d.ts.map +1 -0
  55. package/dist/widget/icons.d.ts +5 -0
  56. package/dist/widget/icons.d.ts.map +1 -1
  57. package/dist/widget/index.cjs +3035 -2465
  58. package/dist/widget/index.cjs.map +1 -1
  59. package/dist/widget/index.d.ts +3 -0
  60. package/dist/widget/index.d.ts.map +1 -1
  61. package/dist/widget/index.js +1636 -606
  62. package/dist/widget/index.js.map +1 -1
  63. package/dist/widget/legendValues.d.ts +14 -0
  64. package/dist/widget/legendValues.d.ts.map +1 -0
  65. package/dist/widget/types.d.ts +34 -8
  66. package/dist/widget/types.d.ts.map +1 -1
  67. package/dist/widget/widgetConfig.d.ts +1 -5
  68. package/dist/widget/widgetConfig.d.ts.map +1 -1
  69. package/dist/widget/widgetTimeframes.d.ts +20 -0
  70. package/dist/widget/widgetTimeframes.d.ts.map +1 -0
  71. package/package.json +3 -3
  72. package/dist/DragDropImporter-BcTzFeRP.js.map +0 -1
  73. package/dist/DragDropImporter-DZBrretS.cjs +0 -2
  74. package/dist/DragDropImporter-DZBrretS.cjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","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/i18n.ts","../../src/widget/WidgetLoadingOverlay.ts","../../src/widget/ChartWidget.ts"],"sourcesContent":["import type { DataSeries, OHLCBar, TimeFrame } from '@tradecanvas/commons';\r\nimport { timeframeToMs, timeframeBucketStart } from '@tradecanvas/commons';\r\n\r\nexport interface ResampleOptions {\r\n /** 0 = Sunday, 1 = Monday (default) — anchor for weekly buckets. */\r\n weekStartsOn?: 0 | 1;\r\n}\r\n\r\n/**\r\n * Aggregate a finer OHLCV series into a coarser timeframe.\r\n *\r\n * Bars are grouped by calendar-aware bucket (see `timeframeBucketStart`):\r\n * open = first bar's open, high/low = extremes, close = last bar's close,\r\n * volume = sum. Input bars are assumed sorted ascending by `time` and are\r\n * never mutated.\r\n *\r\n * Upsampling (target finer than source) cannot synthesize data — pass a target\r\n * coarser than the source. Use `inferTimeframeMs` to detect the source spacing.\r\n */\r\nexport function resampleOHLCV(\r\n bars: DataSeries,\r\n target: TimeFrame,\r\n opts: ResampleOptions = {},\r\n): DataSeries {\r\n if (bars.length === 0) return [];\r\n const weekStartsOn = opts.weekStartsOn ?? 1;\r\n\r\n const out: OHLCBar[] = [];\r\n let current: OHLCBar | null = null;\r\n let currentKey = Number.NaN;\r\n\r\n for (const bar of bars) {\r\n const key = timeframeBucketStart(bar.time, target, weekStartsOn);\r\n if (current === null || key !== currentKey) {\r\n if (current !== null) out.push(current);\r\n current = {\r\n time: key,\r\n open: bar.open,\r\n high: bar.high,\r\n low: bar.low,\r\n close: bar.close,\r\n volume: bar.volume,\r\n };\r\n currentKey = key;\r\n } else {\r\n current = {\r\n time: current.time,\r\n open: current.open,\r\n high: Math.max(current.high, bar.high),\r\n low: Math.min(current.low, bar.low),\r\n close: bar.close,\r\n volume: current.volume + bar.volume,\r\n };\r\n }\r\n }\r\n if (current !== null) out.push(current);\r\n return out;\r\n}\r\n\r\n/**\r\n * Estimate the source bar spacing in milliseconds from the median gap between\r\n * consecutive bars. Robust to occasional gaps (weekends, halts). Returns 0 for\r\n * series with fewer than two bars.\r\n */\r\nexport function inferTimeframeMs(bars: DataSeries): number {\r\n if (bars.length < 2) return 0;\r\n const gaps: number[] = [];\r\n for (let i = 1; i < bars.length; i++) {\r\n const gap = bars[i].time - bars[i - 1].time;\r\n if (gap > 0) gaps.push(gap);\r\n }\r\n if (gaps.length === 0) return 0;\r\n gaps.sort((a, b) => a - b);\r\n return gaps[Math.floor(gaps.length / 2)];\r\n}\r\n\r\n/**\r\n * Whether `target` is coarser than (or equal to) the source spacing, i.e. a\r\n * valid downsample. A non-positive `sourceMs` (unknown) is treated as valid.\r\n */\r\nexport function canResample(sourceMs: number, target: TimeFrame): boolean {\r\n if (sourceMs <= 0) return true;\r\n return timeframeToMs(target) >= sourceMs;\r\n}\r\n","import type { ChartType, DrawingToolType, TimeFrame } from '@tradecanvas/commons';\r\nimport type { IndicatorDef, DrawingToolGroupDef, ChartSettingsState } from './types.js';\r\n\r\nexport const TIMEFRAMES: { label: string; value: TimeFrame }[] = [\r\n { label: '1m', value: '1m' },\r\n { label: '5m', value: '5m' },\r\n { label: '15m', value: '15m' },\r\n { label: '1H', value: '1h' },\r\n { label: '4H', value: '4h' },\r\n { label: '1D', value: '1d' },\r\n];\r\n\r\nexport const CHART_TYPES: { label: string; value: ChartType }[] = [\r\n { label: 'Candlestick', value: 'candlestick' },\r\n { label: 'Line', value: 'line' },\r\n { label: 'Area', value: 'area' },\r\n { label: 'Bar', value: 'bar' },\r\n { label: 'Heikin-Ashi', value: 'heikinAshi' },\r\n { label: 'Hollow Candle', value: 'hollowCandle' },\r\n { label: 'Baseline', value: 'baseline' },\r\n { label: 'Volume Candles', value: 'volumeCandles' },\r\n { label: 'Equivolume', value: 'equivolume' },\r\n { label: 'HLC Area', value: 'hlcArea' },\r\n { label: 'Step Line', value: 'stepLine' },\r\n { label: 'Line + Markers', value: 'lineWithMarkers' },\r\n];\r\n\r\nexport const DRAWING_TOOL_GROUPS: DrawingToolGroupDef[] = [\r\n {\r\n label: 'Lines',\r\n tools: [\r\n { label: 'Trend Line', value: 'trendLine' as DrawingToolType },\r\n { label: 'Ray', value: 'ray' as DrawingToolType },\r\n { label: 'Extended Line', value: 'extendedLine' as DrawingToolType },\r\n { label: 'Info Line', value: 'infoLine' as DrawingToolType },\r\n { label: 'Trend Angle', value: 'trendAngle' as DrawingToolType },\r\n ],\r\n },\r\n {\r\n label: 'Horizontal/Vertical',\r\n tools: [\r\n { label: 'Horizontal Line', value: 'horizontalLine' as DrawingToolType },\r\n { label: 'Horizontal Ray', value: 'horizontalRay' as DrawingToolType },\r\n { label: 'Vertical Line', value: 'verticalLine' as DrawingToolType },\r\n { label: 'Cross Line', value: 'crossLine' as DrawingToolType },\r\n ],\r\n },\r\n {\r\n label: 'Channels',\r\n tools: [\r\n { label: 'Parallel Channel', value: 'parallelChannel' as DrawingToolType },\r\n { label: 'Regression Channel', value: 'regressionChannel' as DrawingToolType },\r\n ],\r\n },\r\n {\r\n label: 'Fibonacci',\r\n tools: [\r\n { label: 'Fib Retracement', value: 'fibRetracement' as DrawingToolType },\r\n { label: 'Fib Extension', value: 'fibExtension' as DrawingToolType },\r\n { label: 'Fib Channel', value: 'fibChannel' as DrawingToolType },\r\n { label: 'Fib Time Zones', value: 'fibTimeZones' as DrawingToolType },\r\n { label: 'Fib Speed Resistance Fan', value: 'fibSpeedResistanceFan' as DrawingToolType },\r\n ],\r\n },\r\n {\r\n label: 'Shapes',\r\n tools: [\r\n { label: 'Rectangle', value: 'rectangle' as DrawingToolType },\r\n { label: 'Circle', value: 'circle' as DrawingToolType },\r\n { label: 'Ellipse', value: 'ellipse' as DrawingToolType },\r\n { label: 'Triangle', value: 'triangle' as DrawingToolType },\r\n ],\r\n },\r\n {\r\n label: 'Gann & Pitchforks',\r\n tools: [\r\n { label: 'Pitchfork', value: 'pitchfork' as DrawingToolType },\r\n { label: 'Schiff Pitchfork', value: 'schiffPitchfork' as DrawingToolType },\r\n { label: 'Modified Schiff Pitchfork', value: 'modifiedSchiffPitchfork' as DrawingToolType },\r\n { label: 'Gann Fan', value: 'gannFan' as DrawingToolType },\r\n { label: 'Gann Box', value: 'gannBox' as DrawingToolType },\r\n { label: 'Cyclic Lines', value: 'cyclicLines' as DrawingToolType },\r\n ],\r\n },\r\n {\r\n label: 'Patterns',\r\n tools: [\r\n { label: 'XABCD Pattern', value: 'xabcdPattern' as DrawingToolType },\r\n { label: 'ABCD Pattern', value: 'abcdPattern' as DrawingToolType },\r\n { label: 'Head and Shoulders', value: 'headAndShoulders' as DrawingToolType },\r\n { label: 'Elliott Wave', value: 'elliottWave' as DrawingToolType },\r\n ],\r\n },\r\n {\r\n label: 'Measure',\r\n tools: [\r\n { label: 'Price Range', value: 'priceRange' as DrawingToolType },\r\n { label: 'Date Range', value: 'dateRange' as DrawingToolType },\r\n { label: 'Date and Price Range', value: 'dateAndPriceRange' as DrawingToolType },\r\n { label: 'Measure', value: 'measure' as DrawingToolType },\r\n ],\r\n },\r\n {\r\n label: 'Annotation',\r\n tools: [\r\n { label: 'Text', value: 'text' as DrawingToolType },\r\n { label: 'Price Label', value: 'priceLabel' as DrawingToolType },\r\n { label: 'Arrow', value: 'arrow' as DrawingToolType },\r\n ],\r\n },\r\n {\r\n label: 'Forecasting',\r\n tools: [\r\n { label: 'Long/Short Position', value: 'riskReward' as DrawingToolType },\r\n { label: 'Anchored VWAP', value: 'anchoredVWAP' as DrawingToolType },\r\n { label: 'Fixed Range Volume Profile', value: 'volumeProfileRange' as DrawingToolType },\r\n ],\r\n },\r\n];\r\n\r\nexport const INDICATORS: IndicatorDef[] = [\r\n { id: 'sma', name: 'SMA', type: 'overlay' },\r\n { id: 'ema', name: 'EMA', type: 'overlay' },\r\n { id: 'tema', name: 'Triple EMA', type: 'overlay' },\r\n { id: 'vwma', name: 'VWMA', type: 'overlay' },\r\n { id: 'wma', name: 'Weighted MA', type: 'overlay' },\r\n { id: 'hma', name: 'Hull MA', type: 'overlay' },\r\n { id: 'mtfma', name: 'MTF Moving Average', type: 'overlay' },\r\n { id: 'bb', name: 'Bollinger Bands', type: 'overlay' },\r\n { id: 'envelope', name: 'Envelope', type: 'overlay' },\r\n { id: 'vwap', name: 'VWAP', type: 'overlay' },\r\n { id: 'avwap', name: 'Anchored VWAP', type: 'overlay' },\r\n { id: 'svwap', name: 'Session VWAP', type: 'overlay' },\r\n { id: 'ichimoku', name: 'Ichimoku Cloud', type: 'overlay' },\r\n { id: 'psar', name: 'Parabolic SAR', type: 'overlay' },\r\n { id: 'supertrend', name: 'Supertrend', type: 'overlay' },\r\n { id: 'keltner', name: 'Keltner Channel', type: 'overlay' },\r\n { id: 'donchian', name: 'Donchian Channel', type: 'overlay' },\r\n { id: 'pivots', name: 'Pivot Points', type: 'overlay' },\r\n { id: 'zigzag', name: 'ZigZag', type: 'overlay' },\r\n { id: 'lrc', name: 'Linear Regression Channel', type: 'overlay' },\r\n { id: 'chandelier', name: 'Chandelier Exit', type: 'overlay' },\r\n { id: 'alligator', name: 'Alligator', type: 'overlay' },\r\n { id: 'rsi', name: 'RSI', type: 'panel' },\r\n { id: 'macd', name: 'MACD', type: 'panel' },\r\n { id: 'stochastic', name: 'Stochastic', type: 'panel' },\r\n { id: 'atr', name: 'ATR', type: 'panel' },\r\n { id: 'adx', name: 'ADX', type: 'panel' },\r\n { id: 'obv', name: 'OBV', type: 'panel' },\r\n { id: 'williamsR', name: 'Williams %R', type: 'panel' },\r\n { id: 'cci', name: 'CCI', type: 'panel' },\r\n { id: 'mfi', name: 'MFI', type: 'panel' },\r\n { id: 'roc', name: 'ROC', type: 'panel' },\r\n { id: 'tsi', name: 'TSI', type: 'panel' },\r\n { id: 'cmf', name: 'CMF', type: 'panel' },\r\n { id: 'aroon', name: 'Aroon', type: 'panel' },\r\n { id: 'stddev', name: 'Std Deviation', type: 'panel' },\r\n { id: 'vroc', name: 'Volume ROC', type: 'panel' },\r\n { id: 'ad', name: 'Acc/Dist', type: 'panel' },\r\n { id: 'ao', name: 'Awesome Oscillator', type: 'panel' },\r\n { id: 'chaikinOsc', name: 'Chaikin Oscillator', type: 'panel' },\r\n { id: 'voldelta', name: 'Volume Delta', type: 'panel' },\r\n { id: 'vortex', name: 'Vortex Indicator', type: 'panel' },\r\n { id: 'chop', name: 'Choppiness Index', type: 'panel' },\r\n { id: 'uo', name: 'Ultimate Oscillator', type: 'panel' },\r\n { id: 'fi', name: 'Force Index', type: 'panel' },\r\n { id: 'crsi', name: 'Connors RSI', type: 'panel' },\r\n { id: 'coppock', name: 'Coppock Curve', type: 'panel' },\r\n { id: 'kst', name: 'Know Sure Thing', type: 'panel' },\r\n { id: 'elderray', name: 'Elder Ray', type: 'panel' },\r\n { id: 'stc', name: 'Schaff Trend Cycle', type: 'panel' },\r\n { id: 'kvo', name: 'Klinger Oscillator', type: 'panel' },\r\n { id: 'fisher', name: 'Fisher Transform', type: 'panel' },\r\n { id: 'dpo', name: 'Detrended Price Osc', type: 'panel' },\r\n { id: 'bop', name: 'Balance of Power', type: 'panel' },\r\n { id: 'massindex', name: 'Mass Index', type: 'panel' },\r\n { id: 'cmo', name: 'Chande Momentum', type: 'panel' },\r\n { id: 'trix', name: 'TRIX', type: 'panel' },\r\n { id: 'emv', name: 'Ease of Movement', type: 'panel' },\r\n { id: 'pvt', name: 'Price Volume Trend', type: 'panel' },\r\n { id: 'wad', name: 'Williams A/D', type: 'panel' },\r\n { id: 'chaikinvol', name: 'Chaikin Volatility', type: 'panel' },\r\n { id: 'rvi', name: 'Relative Vigor Index', type: 'panel' },\r\n { id: 'stochrsi', name: 'Stochastic RSI', type: 'panel' },\r\n { id: 'ppo', name: 'Percentage Price Oscillator', type: 'panel' },\r\n { id: 'ac', name: 'Accelerator Oscillator', type: 'panel' },\r\n { id: 'rmi', name: 'Relative Momentum Index', type: 'panel' },\r\n { id: 'disparity', name: 'Disparity Index', type: 'panel' },\r\n { id: 'qstick', name: 'Qstick', type: 'panel' },\r\n { id: 'pgo', name: 'Pretty Good Oscillator', type: 'panel' },\r\n { id: 'volumeProfile', name: 'Volume Profile', type: 'panel' },\r\n];\r\n\r\nexport const POPULAR_INDICATORS = [\r\n 'sma', 'ema', 'bb', 'rsi', 'macd', 'stochastic',\r\n 'vwap', 'atr', 'obv', 'ichimoku',\r\n];\r\n\r\nexport const DEFAULT_SYMBOLS = [\r\n 'BTCUSDT', 'ETHUSDT', 'SOLUSDT', 'BNBUSDT',\r\n];\r\n\r\nexport const DEFAULT_SETTINGS: ChartSettingsState = {\r\n candleUpColor: '#26A69A',\r\n candleDownColor: '#EF5350',\r\n candleUpWick: '#26A69A',\r\n candleDownWick: '#EF5350',\r\n backgroundColor: '#131722',\r\n gridColor: '#1E222D',\r\n gridVisible: true,\r\n volumeVisible: true,\r\n volumeProfileVisible: false,\r\n marketProfileVisible: false,\r\n marketProfileSplit: false,\r\n marketProfileLetters: false,\r\n marketProfileBuckets: 48,\r\n marketProfileOpacity: 0.32,\r\n depthHeatmapVisible: false,\r\n depthHeatmapOpacity: 0.7,\r\n sessionShadingVisible: false,\r\n pivotMarkersVisible: false,\r\n pivotStrength: 5,\r\n pivotStructureLabels: false,\r\n periodLevelsVisible: false,\r\n periodLevelsPeriod: 'day',\r\n legendVisible: true,\r\n barCountdown: true,\r\n logScale: false,\r\n scaleMode: 'regular',\r\n autoScale: true,\r\n crosshairMode: 'magnet',\r\n numberLocale: 'en-US',\r\n timezone: 'local',\r\n};\r\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> = {\r\n cursor: '<path d=\"M3 3l7.07 16.97 2.51-7.39 7.39-2.51L3 3z\"/><path d=\"M13 13l6 6\"/>',\r\n trendingUp: '<polyline points=\"22 7 13.5 15.5 8.5 10.5 2 17\"/><polyline points=\"16 7 22 7 22 13\"/>',\r\n minus: '<path d=\"M5 12h14\"/>',\r\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\"/>',\r\n zigzag: '<polyline points=\"2 18 7 8 12 14 17 4 22 12\"/>',\r\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\"/>',\r\n square: '<rect width=\"18\" height=\"18\" x=\"3\" y=\"3\" rx=\"2\"/>',\r\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\"/>',\r\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\"/>',\r\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\"/>',\r\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\"/>',\r\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\"/>',\r\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\"/>',\r\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\"/>',\r\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\"/>',\r\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\"/>',\r\n moon: '<path d=\"M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z\"/>',\r\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\"/>',\r\n chevronDown: '<path d=\"m6 9 6 6 6-6\"/>',\r\n chevronUp: '<path d=\"m18 15-6-6-6 6\"/>',\r\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\"/>',\r\n x: '<path d=\"M18 6 6 18\"/><path d=\"m6 6 12 12\"/>',\r\n play: '<polygon points=\"6 3 20 12 6 21 6 3\"/>',\r\n pause: '<rect width=\"4\" height=\"16\" x=\"6\" y=\"4\"/><rect width=\"4\" height=\"16\" x=\"14\" y=\"4\"/>',\r\n stop: '<rect width=\"14\" height=\"14\" x=\"5\" y=\"5\" rx=\"1\"/>',\r\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\"/>',\r\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\"/>',\r\n plus: '<path d=\"M5 12h14\"/><path d=\"M12 5v14\"/>',\r\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\"/>',\r\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\"/>',\r\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\"/>',\r\n lock: '<rect width=\"18\" height=\"11\" x=\"3\" y=\"11\" rx=\"2\"/><path d=\"M7 11V7a5 5 0 0 1 10 0v4\"/>',\r\n unlock: '<rect width=\"18\" height=\"11\" x=\"3\" y=\"11\" rx=\"2\"/><path d=\"M7 11V7a5 5 0 0 1 9.9-1\"/>',\r\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\"/>',\r\n trendingDown: '<polyline points=\"22 17 13.5 8.5 8.5 13.5 2 7\"/><polyline points=\"16 17 22 17 22 11\"/>',\r\n check: '<polyline points=\"20 6 9 17 4 12\"/>',\r\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\"/>',\r\n};\r\n\r\nexport function createIcon(name: string, size = 14): string {\r\n const paths = ICON_PATHS[name];\r\n if (!paths) return '';\r\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>`;\r\n}\r\n","export class WidgetDropdown {\r\n private trigger: HTMLElement;\r\n private panel: HTMLDivElement;\r\n private _isOpen = false;\r\n private onOutsideClick: (e: MouseEvent) => void;\r\n private onEscapeKey: (e: KeyboardEvent) => void;\r\n private onTriggerClick: () => void;\r\n\r\n constructor(trigger: HTMLElement, config: { width?: string; align?: 'left' | 'right' } = {}) {\r\n this.trigger = trigger;\r\n\r\n this.panel = document.createElement('div');\r\n this.panel.className = 'tcw-dropdown';\r\n this.panel.style.width = config.width ?? '200px';\r\n if (config.align === 'right') {\r\n this.panel.style.right = '0';\r\n } else {\r\n this.panel.style.left = '0';\r\n }\r\n this.panel.style.display = 'none';\r\n\r\n // Position relative to trigger\r\n trigger.style.position = 'relative';\r\n trigger.appendChild(this.panel);\r\n\r\n this.onTriggerClick = () => {\r\n if (this._isOpen) {\r\n this.close();\r\n } else {\r\n this.open();\r\n }\r\n };\r\n\r\n this.onOutsideClick = (e: MouseEvent) => {\r\n if (!this.trigger.contains(e.target as Node)) {\r\n this.close();\r\n }\r\n };\r\n\r\n this.onEscapeKey = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape') {\r\n this.close();\r\n }\r\n };\r\n\r\n trigger.addEventListener('click', this.onTriggerClick);\r\n }\r\n\r\n setContent(html: string): void {\r\n this.panel.innerHTML = html;\r\n }\r\n\r\n open(): void {\r\n if (this._isOpen) return;\r\n this._isOpen = true;\r\n this.panel.style.display = '';\r\n document.addEventListener('mousedown', this.onOutsideClick);\r\n document.addEventListener('keydown', this.onEscapeKey);\r\n }\r\n\r\n close(): void {\r\n if (!this._isOpen) return;\r\n this._isOpen = false;\r\n this.panel.style.display = 'none';\r\n document.removeEventListener('mousedown', this.onOutsideClick);\r\n document.removeEventListener('keydown', this.onEscapeKey);\r\n }\r\n\r\n isOpen(): boolean {\r\n return this._isOpen;\r\n }\r\n\r\n destroy(): void {\r\n this.trigger.removeEventListener('click', this.onTriggerClick);\r\n document.removeEventListener('mousedown', this.onOutsideClick);\r\n document.removeEventListener('keydown', this.onEscapeKey);\r\n this.panel.remove();\r\n }\r\n}\r\n","import type { ChartType } from '@tradecanvas/commons';\r\nimport type { ToolbarConfig, ToolbarCallbacks, WidgetState, ActiveIndicator } from './types.js';\r\nimport { createIcon } from './icons.js';\r\nimport { WidgetDropdown } from './WidgetDropdown.js';\r\nimport type { Translator } from './i18n.js';\r\n\r\nexport class WidgetToolbar {\r\n private config: ToolbarConfig;\r\n private callbacks: ToolbarCallbacks;\r\n private t: Translator;\r\n private el: HTMLDivElement;\r\n private chartTypeDropdown: WidgetDropdown | null = null;\r\n private indicatorDropdown: WidgetDropdown | null = null;\r\n private tfButtons: HTMLButtonElement[] = [];\r\n private chipsContainer: HTMLDivElement | null = null;\r\n private themeBtn: HTMLButtonElement | null = null;\r\n\r\n constructor(host: HTMLElement, config: ToolbarConfig, callbacks: ToolbarCallbacks, t: Translator) {\r\n this.config = config;\r\n this.callbacks = callbacks;\r\n this.t = t;\r\n this.el = document.createElement('div');\r\n this.el.className = 'tcw-toolbar';\r\n this.build();\r\n host.appendChild(this.el);\r\n }\r\n\r\n private build(): void {\r\n const { config, callbacks, el } = this;\r\n\r\n // Symbol button\r\n const symbolBtn = document.createElement('button');\r\n symbolBtn.className = 'tcw-toolbar-symbol';\r\n symbolBtn.dataset.role = 'symbol';\r\n symbolBtn.addEventListener('click', callbacks.onSymbolClick);\r\n el.appendChild(symbolBtn);\r\n el.appendChild(this.sep());\r\n\r\n // Timeframes\r\n const tfGroup = document.createElement('div');\r\n tfGroup.className = 'tcw-toolbar-group';\r\n for (const tf of config.timeframes) {\r\n const btn = document.createElement('button');\r\n btn.className = 'tcw-btn';\r\n btn.textContent = tf.label;\r\n btn.dataset.tf = tf.value;\r\n btn.addEventListener('click', () => callbacks.onTimeframe(tf.value));\r\n tfGroup.appendChild(btn);\r\n this.tfButtons.push(btn);\r\n }\r\n el.appendChild(tfGroup);\r\n el.appendChild(this.sep());\r\n\r\n // Chart type dropdown\r\n const ctWrap = document.createElement('div');\r\n ctWrap.style.position = 'relative';\r\n ctWrap.style.display = 'inline-flex';\r\n\r\n const ctTrigger = document.createElement('button');\r\n ctTrigger.className = 'tcw-dropdown-trigger';\r\n ctTrigger.dataset.role = 'charttype';\r\n ctWrap.appendChild(ctTrigger);\r\n el.appendChild(ctWrap);\r\n\r\n this.chartTypeDropdown = new WidgetDropdown(ctWrap, { width: '160px' });\r\n this.buildChartTypeMenu();\r\n\r\n el.appendChild(this.sep());\r\n\r\n // Indicators dropdown\r\n const indWrap = document.createElement('div');\r\n indWrap.style.position = 'relative';\r\n indWrap.style.display = 'inline-flex';\r\n\r\n const indTrigger = document.createElement('button');\r\n indTrigger.className = 'tcw-dropdown-trigger';\r\n indTrigger.dataset.role = 'indicators';\r\n indWrap.appendChild(indTrigger);\r\n el.appendChild(indWrap);\r\n\r\n this.indicatorDropdown = new WidgetDropdown(indWrap, { width: '280px' });\r\n this.buildIndicatorMenu();\r\n\r\n // Indicator chips\r\n this.chipsContainer = document.createElement('div');\r\n this.chipsContainer.className = 'tcw-indicator-chips';\r\n el.appendChild(this.chipsContainer);\r\n\r\n // Spacer\r\n el.appendChild(this.spacer());\r\n\r\n // Right side buttons\r\n if (callbacks.onToggleReplay) {\r\n const replayBtn = this.iconBtn('play', this.t('toolbar.replay'), callbacks.onToggleReplay);\r\n replayBtn.dataset.role = 'replay';\r\n el.appendChild(replayBtn);\r\n }\r\n\r\n if (callbacks.onBracket) {\r\n const onBracket = callbacks.onBracket;\r\n const longBtn = this.iconBtn('trendingUp', this.t('toolbar.longBracket'), () => onBracket('buy'));\r\n longBtn.dataset.role = 'long';\r\n longBtn.classList.add('tcw-btn-long');\r\n el.appendChild(longBtn);\r\n const shortBtn = this.iconBtn('trendingDown', this.t('toolbar.shortBracket'), () => onBracket('sell'));\r\n shortBtn.dataset.role = 'short';\r\n shortBtn.classList.add('tcw-btn-short');\r\n el.appendChild(shortBtn);\r\n }\r\n\r\n if (callbacks.onToggleLadder) {\r\n const ladderBtn = this.iconBtn('ladder', this.t('toolbar.depthLadder'), callbacks.onToggleLadder);\r\n ladderBtn.dataset.role = 'ladder';\r\n el.appendChild(ladderBtn);\r\n }\r\n\r\n if (callbacks.onToggleObjects) {\r\n const objectsBtn = this.iconBtn('layers', this.t('toolbar.objects'), callbacks.onToggleObjects);\r\n objectsBtn.dataset.role = 'objects';\r\n el.appendChild(objectsBtn);\r\n }\r\n\r\n if (callbacks.onToggleAlerts) {\r\n const alertsBtn = this.iconBtn('bell', this.t('toolbar.priceAlerts'), callbacks.onToggleAlerts);\r\n alertsBtn.dataset.role = 'alerts';\r\n el.appendChild(alertsBtn);\r\n }\r\n\r\n const screenshotBtn = this.iconBtn('camera', this.t('toolbar.screenshot'), callbacks.onScreenshot);\r\n el.appendChild(screenshotBtn);\r\n\r\n const settingsBtn = this.iconBtn('settings', this.t('toolbar.settings'), callbacks.onSettings);\r\n el.appendChild(settingsBtn);\r\n\r\n this.themeBtn = this.iconBtn('moon', this.t('toolbar.toggleTheme'), callbacks.onToggleTheme);\r\n this.themeBtn.dataset.role = 'theme';\r\n el.appendChild(this.themeBtn);\r\n }\r\n\r\n private chartTypeLabel(ct: { value: ChartType; label: string }): string {\r\n const key = `chartType.${ct.value}` as const;\r\n const translated = this.t(key as Parameters<Translator>[0]);\r\n return translated === key ? ct.label : translated;\r\n }\r\n\r\n private buildChartTypeMenu(): void {\r\n if (!this.chartTypeDropdown) return;\r\n const items = this.config.chartTypes.map(ct =>\r\n `<button class=\"tcw-dropdown-item\" data-ct=\"${ct.value}\">${this.chartTypeLabel(ct)}</button>`\r\n ).join('');\r\n this.chartTypeDropdown.setContent(items);\r\n\r\n // Attach events to items after content set\r\n const panel = this.chartTypeDropdown['panel'] as HTMLDivElement;\r\n panel.querySelectorAll('.tcw-dropdown-item').forEach((btn) => {\r\n btn.addEventListener('click', (e) => {\r\n const value = (e.currentTarget as HTMLElement).dataset.ct as ChartType;\r\n this.callbacks.onChartType(value);\r\n this.chartTypeDropdown?.close();\r\n });\r\n });\r\n }\r\n\r\n private buildIndicatorMenu(): void {\r\n if (!this.indicatorDropdown) return;\r\n const { indicators, popularIndicatorIds } = this.config;\r\n\r\n const popular = indicators.filter(d => popularIndicatorIds.includes(d.id));\r\n const other = indicators.filter(d => !popularIndicatorIds.includes(d.id));\r\n\r\n const typeLabel = (type: string) => this.t(`indicatorType.${type}` as Parameters<Translator>[0]);\r\n\r\n let html = `<div class=\"tcw-dropdown-label\">${this.t('toolbar.indicators.popular')}</div>`;\r\n for (const ind of popular) {\r\n html += `<button class=\"tcw-dropdown-item\" data-ind=\"${ind.id}\"><span>${ind.name}</span><span class=\"tcw-tag\">${typeLabel(ind.type)}</span></button>`;\r\n }\r\n html += '<div class=\"tcw-dropdown-divider\"></div>';\r\n html += `<div class=\"tcw-dropdown-label\">${this.t('toolbar.indicators.all')}</div>`;\r\n for (const ind of other) {\r\n html += `<button class=\"tcw-dropdown-item\" data-ind=\"${ind.id}\"><span>${ind.name}</span><span class=\"tcw-tag\">${typeLabel(ind.type)}</span></button>`;\r\n }\r\n\r\n this.indicatorDropdown.setContent(html);\r\n\r\n const panel = this.indicatorDropdown['panel'] as HTMLDivElement;\r\n panel.querySelectorAll('.tcw-dropdown-item[data-ind]').forEach((btn) => {\r\n btn.addEventListener('click', (e) => {\r\n const id = (e.currentTarget as HTMLElement).dataset.ind!;\r\n this.callbacks.onAddIndicator(id);\r\n });\r\n });\r\n }\r\n\r\n update(state: WidgetState): void {\r\n // Symbol\r\n const symbolBtn = this.el.querySelector('[data-role=\"symbol\"]') as HTMLButtonElement | null;\r\n if (symbolBtn) symbolBtn.textContent = state.symbol;\r\n\r\n // Timeframe buttons\r\n for (const btn of this.tfButtons) {\r\n btn.classList.toggle('tcw-active', btn.dataset.tf === state.timeframe);\r\n }\r\n\r\n // Chart type trigger label\r\n const ctTrigger = this.el.querySelector('[data-role=\"charttype\"]') as HTMLElement | null;\r\n if (ctTrigger) {\r\n const ct = this.config.chartTypes.find(ct => ct.value === state.chartType);\r\n const label = ct ? this.chartTypeLabel(ct) : state.chartType;\r\n ctTrigger.innerHTML = `${createIcon('barChart', 14)} ${label} ${createIcon('chevronDown', 12)}`;\r\n }\r\n\r\n // Indicator trigger + badge\r\n const indTrigger = this.el.querySelector('[data-role=\"indicators\"]') as HTMLElement | null;\r\n if (indTrigger) {\r\n const count = state.activeIndicators.size;\r\n let inner = `${createIcon('trendingUp', 14)} ${this.t('toolbar.indicators')}`;\r\n if (count > 0) {\r\n inner += ` <span class=\"tcw-badge-count\">${count}</span>`;\r\n }\r\n indTrigger.innerHTML = inner;\r\n }\r\n\r\n // Chips\r\n if (this.chipsContainer) {\r\n const activeList = this.getActiveIndicatorList(state);\r\n this.chipsContainer.innerHTML = '';\r\n for (const ind of activeList) {\r\n const chip = document.createElement('div');\r\n chip.className = 'tcw-indicator-chip';\r\n\r\n const label = document.createElement('span');\r\n label.textContent = ind.label;\r\n chip.appendChild(label);\r\n\r\n const removeBtn = document.createElement('button');\r\n removeBtn.className = 'tcw-chip-remove';\r\n removeBtn.innerHTML = createIcon('x', 10);\r\n removeBtn.addEventListener('click', () => this.callbacks.onRemoveIndicator(ind.instanceId));\r\n chip.appendChild(removeBtn);\r\n\r\n this.chipsContainer.appendChild(chip);\r\n }\r\n }\r\n\r\n // Theme toggle icon\r\n if (this.themeBtn) {\r\n this.themeBtn.innerHTML = state.isDark ? createIcon('moon', 14) : createIcon('sun', 14);\r\n }\r\n }\r\n\r\n private getActiveIndicatorList(state: WidgetState): ActiveIndicator[] {\r\n const result: ActiveIndicator[] = [];\r\n for (const [id, instanceId] of state.activeIndicators.entries()) {\r\n result.push({ instanceId, id, label: id.toUpperCase() });\r\n }\r\n return result;\r\n }\r\n\r\n private sep(): HTMLSpanElement {\r\n const s = document.createElement('span');\r\n s.className = 'tcw-toolbar-sep';\r\n return s;\r\n }\r\n\r\n private spacer(): HTMLSpanElement {\r\n const s = document.createElement('span');\r\n s.className = 'tcw-toolbar-spacer';\r\n return s;\r\n }\r\n\r\n private iconBtn(icon: string, title: string, onClick: () => void): HTMLButtonElement {\r\n const btn = document.createElement('button');\r\n btn.className = 'tcw-btn-icon';\r\n btn.title = title;\r\n btn.innerHTML = createIcon(icon, 14);\r\n btn.addEventListener('click', onClick);\r\n return btn;\r\n }\r\n\r\n destroy(): void {\r\n this.chartTypeDropdown?.destroy();\r\n this.indicatorDropdown?.destroy();\r\n this.el.remove();\r\n }\r\n}\r\n","import type { SidebarConfig, SidebarCallbacks, WidgetState } from './types.js';\r\nimport { createIcon } from './icons.js';\r\n\r\nconst GROUP_ICONS = [\r\n 'trendingUp', 'minus', 'penLine', 'hash', 'square', 'gitBranch', 'zigzag', 'ruler', 'type', 'ladder',\r\n];\r\n\r\n/** Icon for a drawing tool in the favorites strip — falls back to a pen. */\r\nconst TOOL_ICONS: Record<string, string> = {\r\n trendLine: 'trendingUp', ray: 'trendingUp', extendedLine: 'trendingUp',\r\n infoLine: 'trendingUp', trendAngle: 'trendingUp',\r\n horizontalLine: 'minus', horizontalRay: 'minus', verticalLine: 'penLine', crossLine: 'plus',\r\n rectangle: 'square', circle: 'square', ellipse: 'square', triangle: 'square', arrow: 'trendingUp',\r\n parallelChannel: 'gitBranch', regressionChannel: 'gitBranch',\r\n pitchfork: 'gitBranch', schiffPitchfork: 'gitBranch', modifiedSchiffPitchfork: 'gitBranch',\r\n fibRetracement: 'hash', fibExtension: 'hash', fibTimeZones: 'hash', fibChannel: 'hash', fibSpeedResistanceFan: 'hash',\r\n gannBox: 'hash', gannFan: 'gitBranch', cyclicLines: 'barChart',\r\n elliottWave: 'zigzag', xabcdPattern: 'zigzag', abcdPattern: 'zigzag', headAndShoulders: 'zigzag',\r\n priceRange: 'ruler', dateRange: 'ruler', dateAndPriceRange: 'ruler', measure: 'ruler',\r\n text: 'type', textAnnotation: 'type', priceLabel: 'type',\r\n anchoredVWAP: 'trendingUp', volumeProfileRange: 'barChart',\r\n riskReward: 'square',\r\n};\r\n\r\nfunction toolIcon(tool: string): string {\r\n return TOOL_ICONS[tool] ?? 'penLine';\r\n}\r\n\r\n/** Human label for a tool id, sourced from the configured groups. */\r\nfunction toolLabel(groups: SidebarConfig['drawingToolGroups'], tool: string): string {\r\n for (const g of groups) {\r\n const t = g.tools.find((x) => x.value === tool);\r\n if (t) return t.label;\r\n }\r\n return tool;\r\n}\r\n\r\nexport class WidgetDrawingSidebar {\r\n private config: SidebarConfig;\r\n private callbacks: SidebarCallbacks;\r\n private el: HTMLDivElement;\r\n private groupWraps: HTMLDivElement[] = [];\r\n private groupButtons: HTMLButtonElement[] = [];\r\n private cursorBtn: HTMLButtonElement | null = null;\r\n private magnetBtn: HTMLButtonElement | null = null;\r\n private flyoutEl: HTMLDivElement | null = null;\r\n private favoritesEl: HTMLDivElement | null = null;\r\n private favoritesDivider: HTMLDivElement | null = null;\r\n private favorites: string[] = [];\r\n\r\n constructor(host: HTMLElement, config: SidebarConfig, callbacks: SidebarCallbacks) {\r\n this.config = config;\r\n this.callbacks = callbacks;\r\n this.el = document.createElement('div');\r\n this.el.className = 'tcw-sidebar';\r\n this.build();\r\n host.appendChild(this.el);\r\n }\r\n\r\n private build(): void {\r\n const { config, callbacks, el } = this;\r\n\r\n // Cursor button\r\n this.cursorBtn = document.createElement('button');\r\n this.cursorBtn.className = 'tcw-sidebar-btn';\r\n this.cursorBtn.title = 'Cursor';\r\n this.cursorBtn.innerHTML = createIcon('cursor', 14);\r\n this.cursorBtn.addEventListener('click', callbacks.onCancelDrawing);\r\n el.appendChild(this.cursorBtn);\r\n\r\n el.appendChild(this.divider());\r\n\r\n // Favorites strip (pinned tools) — only when favorites are enabled.\r\n if (callbacks.onToggleFavorite) {\r\n this.favorites = [...(config.favorites ?? [])];\r\n this.favoritesEl = document.createElement('div');\r\n this.favoritesEl.className = 'tcw-sidebar-favorites';\r\n el.appendChild(this.favoritesEl);\r\n this.favoritesDivider = this.divider();\r\n el.appendChild(this.favoritesDivider);\r\n this.renderFavorites();\r\n }\r\n\r\n // Tool groups\r\n config.drawingToolGroups.forEach((group, idx) => {\r\n const wrap = document.createElement('div');\r\n wrap.className = 'tcw-tool-group-wrap';\r\n\r\n const btn = document.createElement('button');\r\n btn.className = 'tcw-sidebar-btn';\r\n btn.title = group.label;\r\n btn.innerHTML = createIcon(GROUP_ICONS[idx] ?? 'square', 14);\r\n\r\n if (group.tools.length > 1) {\r\n const dot = document.createElement('span');\r\n dot.className = 'tcw-multi-dot';\r\n btn.appendChild(dot);\r\n }\r\n\r\n btn.addEventListener('click', () => callbacks.onDrawingTool(group.tools[0].value));\r\n wrap.appendChild(btn);\r\n\r\n // Flyout events via JS (not CSS hover)\r\n wrap.addEventListener('mouseenter', () => this.showFlyout(idx));\r\n wrap.addEventListener('mouseleave', () => this.hideFlyout());\r\n\r\n el.appendChild(wrap);\r\n this.groupWraps.push(wrap);\r\n this.groupButtons.push(btn);\r\n });\r\n\r\n // Spacer\r\n const spacer = document.createElement('div');\r\n spacer.className = 'tcw-sidebar-spacer';\r\n el.appendChild(spacer);\r\n\r\n el.appendChild(this.divider());\r\n\r\n // Bottom tools\r\n if (callbacks.onToggleStyle) {\r\n const styleBtn = document.createElement('button');\r\n styleBtn.className = 'tcw-sidebar-btn';\r\n styleBtn.title = 'Drawing style & templates';\r\n styleBtn.dataset.role = 'style';\r\n styleBtn.innerHTML = createIcon('palette', 14);\r\n styleBtn.addEventListener('click', callbacks.onToggleStyle);\r\n el.appendChild(styleBtn);\r\n }\r\n\r\n this.magnetBtn = document.createElement('button');\r\n this.magnetBtn.className = 'tcw-sidebar-btn';\r\n this.magnetBtn.title = 'Magnet';\r\n this.magnetBtn.innerHTML = createIcon('magnet', 14);\r\n this.magnetBtn.addEventListener('click', callbacks.onToggleMagnet);\r\n el.appendChild(this.magnetBtn);\r\n\r\n const undoBtn = document.createElement('button');\r\n undoBtn.className = 'tcw-sidebar-btn';\r\n undoBtn.title = 'Undo';\r\n undoBtn.innerHTML = createIcon('undo', 14);\r\n undoBtn.addEventListener('click', callbacks.onUndo);\r\n el.appendChild(undoBtn);\r\n\r\n const redoBtn = document.createElement('button');\r\n redoBtn.className = 'tcw-sidebar-btn';\r\n redoBtn.title = 'Redo';\r\n redoBtn.innerHTML = createIcon('redo', 14);\r\n redoBtn.addEventListener('click', callbacks.onRedo);\r\n el.appendChild(redoBtn);\r\n\r\n const clearBtn = document.createElement('button');\r\n clearBtn.className = 'tcw-sidebar-btn tcw-danger';\r\n clearBtn.title = 'Clear all';\r\n clearBtn.innerHTML = createIcon('trash', 14);\r\n clearBtn.addEventListener('click', callbacks.onClearDrawings);\r\n el.appendChild(clearBtn);\r\n }\r\n\r\n /** Update the pinned-tools strip. */\r\n setFavorites(favorites: string[]): void {\r\n this.favorites = [...favorites];\r\n this.renderFavorites();\r\n }\r\n\r\n private renderFavorites(): void {\r\n if (!this.favoritesEl) return;\r\n this.favoritesEl.replaceChildren();\r\n const visible = this.favorites.length > 0;\r\n this.favoritesEl.style.display = visible ? '' : 'none';\r\n if (this.favoritesDivider) this.favoritesDivider.style.display = visible ? '' : 'none';\r\n\r\n for (const tool of this.favorites) {\r\n const btn = document.createElement('button');\r\n btn.className = 'tcw-sidebar-btn';\r\n btn.title = `${toolLabel(this.config.drawingToolGroups, tool)} (right-click to unpin)`;\r\n btn.dataset.toolValue = tool;\r\n btn.innerHTML = createIcon(toolIcon(tool), 14);\r\n btn.addEventListener('click', () => this.callbacks.onDrawingTool(tool as never));\r\n btn.addEventListener('contextmenu', (e) => {\r\n e.preventDefault();\r\n this.callbacks.onToggleFavorite?.(tool as never);\r\n });\r\n this.favoritesEl.appendChild(btn);\r\n }\r\n }\r\n\r\n private showFlyout(idx: number): void {\r\n const group = this.config.drawingToolGroups[idx];\r\n if (!group || group.tools.length <= 1) return;\r\n\r\n this.hideFlyout();\r\n\r\n const flyout = document.createElement('div');\r\n flyout.className = 'tcw-flyout';\r\n\r\n const header = document.createElement('div');\r\n header.className = 'tcw-flyout-header';\r\n header.textContent = group.label;\r\n flyout.appendChild(header);\r\n\r\n for (const tool of group.tools) {\r\n const item = document.createElement('button');\r\n item.className = 'tcw-flyout-item';\r\n item.textContent = tool.label;\r\n item.dataset.toolValue = tool.value;\r\n item.addEventListener('click', () => {\r\n this.callbacks.onDrawingTool(tool.value);\r\n this.hideFlyout();\r\n });\r\n if (this.callbacks.onToggleFavorite) {\r\n if (this.favorites.includes(tool.value)) item.classList.add('tcw-flyout-faved');\r\n item.title = 'Right-click to pin/unpin';\r\n item.addEventListener('contextmenu', (e) => {\r\n e.preventDefault();\r\n this.callbacks.onToggleFavorite?.(tool.value);\r\n });\r\n }\r\n flyout.appendChild(item);\r\n }\r\n\r\n this.flyoutEl = flyout;\r\n this.groupWraps[idx].appendChild(flyout);\r\n }\r\n\r\n private hideFlyout(): void {\r\n if (this.flyoutEl) {\r\n this.flyoutEl.remove();\r\n this.flyoutEl = null;\r\n }\r\n }\r\n\r\n update(state: WidgetState): void {\r\n // Cursor active\r\n if (this.cursorBtn) {\r\n this.cursorBtn.classList.toggle('tcw-active', state.activeTool === null);\r\n }\r\n\r\n // Group buttons\r\n const { drawingToolGroups } = this.config;\r\n for (let i = 0; i < drawingToolGroups.length; i++) {\r\n const isActive = drawingToolGroups[i].tools.some(t => t.value === state.activeTool);\r\n this.groupButtons[i].classList.toggle('tcw-active', isActive);\r\n }\r\n\r\n // Flyout items\r\n if (this.flyoutEl) {\r\n this.flyoutEl.querySelectorAll('.tcw-flyout-item').forEach((item) => {\r\n const el = item as HTMLElement;\r\n el.classList.toggle('tcw-active', el.dataset.toolValue === state.activeTool);\r\n });\r\n }\r\n\r\n // Magnet\r\n if (this.magnetBtn) {\r\n this.magnetBtn.classList.toggle('tcw-active', state.magnetEnabled);\r\n this.magnetBtn.title = state.magnetEnabled ? 'Magnet ON' : 'Magnet OFF';\r\n }\r\n }\r\n\r\n private divider(): HTMLDivElement {\r\n const d = document.createElement('div');\r\n d.className = 'tcw-sidebar-divider';\r\n return d;\r\n }\r\n\r\n destroy(): void {\r\n this.hideFlyout();\r\n this.el.remove();\r\n }\r\n}\r\n","import type { ChartSettingsState, SettingsCallbacks } from './types.js';\r\nimport { createIcon } from './icons.js';\r\nimport type { Translator } from './i18n.js';\r\n\r\ntype Tab = 'style' | 'display' | 'scale';\r\nconst TABS: Tab[] = ['style', 'display', 'scale'];\r\n\r\nexport class WidgetSettings {\r\n private callbacks: SettingsCallbacks;\r\n private t: Translator;\r\n private backdrop: HTMLDivElement | null = null;\r\n private modal: HTMLDivElement | null = null;\r\n private currentTab: Tab = 'style';\r\n private currentSettings: ChartSettingsState | null = null;\r\n private bodyEl: HTMLDivElement | null = null;\r\n private tabButtons: HTMLButtonElement[] = [];\r\n\r\n constructor(callbacks: SettingsCallbacks, t: Translator) {\r\n this.callbacks = callbacks;\r\n this.t = t;\r\n }\r\n\r\n open(currentSettings: ChartSettingsState): void {\r\n this.currentSettings = { ...currentSettings };\r\n this.currentTab = 'style';\r\n this.buildModal();\r\n }\r\n\r\n close(): void {\r\n this.backdrop?.remove();\r\n this.modal?.remove();\r\n this.backdrop = null;\r\n this.modal = null;\r\n this.bodyEl = null;\r\n this.tabButtons = [];\r\n }\r\n\r\n private buildModal(): void {\r\n // Backdrop\r\n this.backdrop = document.createElement('div');\r\n this.backdrop.className = 'tcw-modal-backdrop';\r\n this.backdrop.addEventListener('click', () => {\r\n this.callbacks.onClose();\r\n this.close();\r\n });\r\n document.body.appendChild(this.backdrop);\r\n\r\n // Modal\r\n this.modal = document.createElement('div');\r\n this.modal.className = 'tcw-modal';\r\n\r\n // Header\r\n const header = document.createElement('div');\r\n header.className = 'tcw-modal-header';\r\n const h3 = document.createElement('h3');\r\n h3.textContent = this.t('settings.title');\r\n header.appendChild(h3);\r\n const closeBtn = document.createElement('button');\r\n closeBtn.className = 'tcw-modal-close';\r\n closeBtn.innerHTML = createIcon('x', 16);\r\n closeBtn.addEventListener('click', () => {\r\n this.callbacks.onClose();\r\n this.close();\r\n });\r\n header.appendChild(closeBtn);\r\n this.modal.appendChild(header);\r\n\r\n // Tabs\r\n const tabsEl = document.createElement('div');\r\n tabsEl.className = 'tcw-modal-tabs';\r\n this.tabButtons = [];\r\n for (const tab of TABS) {\r\n const btn = document.createElement('button');\r\n btn.className = 'tcw-modal-tab';\r\n btn.textContent = this.t(`settings.tab.${tab}` as Parameters<Translator>[0]);\r\n btn.dataset.tab = tab;\r\n if (tab === this.currentTab) btn.classList.add('tcw-active');\r\n btn.addEventListener('click', () => {\r\n this.currentTab = tab;\r\n this.tabButtons.forEach(b => b.classList.toggle('tcw-active', b.dataset.tab === tab));\r\n this.renderTabContent();\r\n });\r\n tabsEl.appendChild(btn);\r\n this.tabButtons.push(btn);\r\n }\r\n this.modal.appendChild(tabsEl);\r\n\r\n // Body\r\n this.bodyEl = document.createElement('div');\r\n this.bodyEl.className = 'tcw-modal-body';\r\n this.modal.appendChild(this.bodyEl);\r\n this.renderTabContent();\r\n\r\n // Footer\r\n const footer = document.createElement('div');\r\n footer.className = 'tcw-modal-footer';\r\n const resetBtn = document.createElement('button');\r\n resetBtn.className = 'tcw-reset-link';\r\n resetBtn.textContent = this.t('settings.resetToDefaults');\r\n resetBtn.addEventListener('click', () => this.callbacks.onReset());\r\n footer.appendChild(resetBtn);\r\n const doneBtn = document.createElement('button');\r\n doneBtn.className = 'tcw-done-btn';\r\n doneBtn.textContent = this.t('settings.done');\r\n doneBtn.addEventListener('click', () => {\r\n this.callbacks.onClose();\r\n this.close();\r\n });\r\n footer.appendChild(doneBtn);\r\n this.modal.appendChild(footer);\r\n\r\n document.body.appendChild(this.modal);\r\n\r\n // Escape key\r\n const onKeyDown = (e: KeyboardEvent) => {\r\n if (e.key === 'Escape') {\r\n document.removeEventListener('keydown', onKeyDown);\r\n this.callbacks.onClose();\r\n this.close();\r\n }\r\n };\r\n document.addEventListener('keydown', onKeyDown);\r\n }\r\n\r\n private renderTabContent(): void {\r\n if (!this.bodyEl || !this.currentSettings) return;\r\n this.bodyEl.innerHTML = '';\r\n\r\n switch (this.currentTab) {\r\n case 'style':\r\n this.renderStyleTab();\r\n break;\r\n case 'display':\r\n this.renderDisplayTab();\r\n break;\r\n case 'scale':\r\n this.renderScaleTab();\r\n break;\r\n }\r\n }\r\n\r\n private renderStyleTab(): void {\r\n if (!this.bodyEl || !this.currentSettings) return;\r\n const s = this.currentSettings;\r\n\r\n // Candle Colors\r\n const candleSection = this.section(this.t('settings.section.candleColors'));\r\n candleSection.appendChild(this.colorRow('Up Body', s.candleUpColor, (v) => this.patch({ candleUpColor: v })));\r\n candleSection.appendChild(this.colorRow('Down Body', s.candleDownColor, (v) => this.patch({ candleDownColor: v })));\r\n candleSection.appendChild(this.colorRow('Up Wick', s.candleUpWick, (v) => this.patch({ candleUpWick: v })));\r\n candleSection.appendChild(this.colorRow('Down Wick', s.candleDownWick, (v) => this.patch({ candleDownWick: v })));\r\n this.bodyEl.appendChild(candleSection);\r\n\r\n // Background\r\n const bgSection = this.section(this.t('settings.section.background'));\r\n bgSection.appendChild(this.colorRow('Background', s.backgroundColor, (v) => this.patch({ backgroundColor: v })));\r\n bgSection.appendChild(this.colorRow('Grid', s.gridColor, (v) => this.patch({ gridColor: v })));\r\n this.bodyEl.appendChild(bgSection);\r\n }\r\n\r\n private renderDisplayTab(): void {\r\n if (!this.bodyEl || !this.currentSettings) return;\r\n const s = this.currentSettings;\r\n\r\n const section = this.section();\r\n section.appendChild(this.toggleRow('Grid Lines', s.gridVisible, (v) => this.patch({ gridVisible: v })));\r\n section.appendChild(this.toggleRow('Volume', s.volumeVisible, (v) => this.patch({ volumeVisible: v })));\r\n section.appendChild(this.toggleRow('Volume Profile', s.volumeProfileVisible, (v) => this.patch({ volumeProfileVisible: v })));\r\n section.appendChild(this.toggleRow('Market Profile (TPO)', s.marketProfileVisible, (v) => this.patch({ marketProfileVisible: v })));\r\n section.appendChild(this.toggleRow('MP split by session', s.marketProfileSplit, (v) => this.patch({ marketProfileSplit: v })));\r\n section.appendChild(this.toggleRow('MP letters (TPO)', s.marketProfileLetters, (v) => this.patch({ marketProfileLetters: v })));\r\n section.appendChild(this.rangeRow('MP buckets', s.marketProfileBuckets, 8, 200, 1, (v) => this.patch({ marketProfileBuckets: v })));\r\n section.appendChild(this.rangeRow('MP opacity', s.marketProfileOpacity, 0.05, 1, 0.05, (v) => this.patch({ marketProfileOpacity: v }), (v) => `${Math.round(v * 100)}%`));\r\n section.appendChild(this.toggleRow('Liquidity heatmap', s.depthHeatmapVisible, (v) => this.patch({ depthHeatmapVisible: v })));\r\n section.appendChild(this.rangeRow('Heatmap opacity', s.depthHeatmapOpacity, 0.1, 1, 0.05, (v) => this.patch({ depthHeatmapOpacity: v }), (v) => `${Math.round(v * 100)}%`));\r\n section.appendChild(this.toggleRow('Swing markers', s.pivotMarkersVisible, (v) => this.patch({ pivotMarkersVisible: v })));\r\n section.appendChild(this.rangeRow('Swing strength', s.pivotStrength, 2, 20, 1, (v) => this.patch({ pivotStrength: v })));\r\n section.appendChild(this.toggleRow('Swing structure (HH/HL)', s.pivotStructureLabels, (v) => this.patch({ pivotStructureLabels: v })));\r\n section.appendChild(this.toggleRow('Session shading (RTH)', s.sessionShadingVisible, (v) => this.patch({ sessionShadingVisible: v })));\r\n section.appendChild(this.toggleRow('Prior-period levels', s.periodLevelsVisible, (v) => this.patch({ periodLevelsVisible: v })));\r\n section.appendChild(this.selectRow('Period levels basis', s.periodLevelsPeriod, [\r\n { value: 'day', label: 'Prior Day (PDH/PDL)' },\r\n { value: 'week', label: 'Prior Week (PWH/PWL)' },\r\n ], (v) => this.patch({ periodLevelsPeriod: v as ChartSettingsState['periodLevelsPeriod'] })));\r\n section.appendChild(this.toggleRow('OHLC Legend', s.legendVisible, (v) => this.patch({ legendVisible: v })));\r\n section.appendChild(this.toggleRow('Bar Countdown', s.barCountdown, (v) => this.patch({ barCountdown: v })));\r\n\r\n // Crosshair mode\r\n section.appendChild(this.selectRow('Crosshair Mode', s.crosshairMode, [\r\n { label: 'Magnet', value: 'magnet' },\r\n { label: 'Normal', value: 'normal' },\r\n { label: 'Hidden', value: 'hidden' },\r\n ], (v) => this.patch({ crosshairMode: v as ChartSettingsState['crosshairMode'] })));\r\n\r\n // Number locale\r\n section.appendChild(this.selectRow('Timezone', s.timezone, [\r\n { value: 'local', label: 'Local' },\r\n { value: '0', label: 'UTC / London' },\r\n { value: '-300', label: 'New York (UTC-5)' },\r\n { value: '-360', label: 'Chicago (UTC-6)' },\r\n { value: '60', label: 'Frankfurt (UTC+1)' },\r\n { value: '480', label: 'Singapore/HK (UTC+8)' },\r\n { value: '540', label: 'Tokyo (UTC+9)' },\r\n { value: '330', label: 'Mumbai (UTC+5:30)' },\r\n ], (v) => this.patch({ timezone: v })));\r\n section.appendChild(this.selectRow('Number Locale', s.numberLocale, [\r\n { label: 'en-US (65,234.00)', value: 'en-US' },\r\n { label: 'de-DE (65.234,00)', value: 'de-DE' },\r\n { label: 'fr-FR (65 234,00)', value: 'fr-FR' },\r\n { label: 'vi-VN (65.234,00)', value: 'vi-VN' },\r\n { label: 'en-IN (65,234.00)', value: 'en-IN' },\r\n { label: 'ja-JP (65,234.00)', value: 'ja-JP' },\r\n ], (v) => this.patch({ numberLocale: v })));\r\n\r\n this.bodyEl.appendChild(section);\r\n }\r\n\r\n private renderScaleTab(): void {\r\n if (!this.bodyEl || !this.currentSettings) return;\r\n const s = this.currentSettings;\r\n\r\n const section = this.section();\r\n section.appendChild(this.toggleRow('Auto Scale', s.autoScale, (v) => this.patch({ autoScale: v })));\r\n section.appendChild(this.selectRow('Price Scale', s.scaleMode, [\r\n { value: 'regular', label: 'Regular' },\r\n { value: 'logarithmic', label: 'Logarithmic' },\r\n { value: 'percentage', label: 'Percentage' },\r\n { value: 'indexedTo100', label: 'Indexed to 100' },\r\n ], (v) => this.patch({ scaleMode: v as ChartSettingsState['scaleMode'] })));\r\n this.bodyEl.appendChild(section);\r\n }\r\n\r\n private patch(partial: Partial<ChartSettingsState>): void {\r\n if (this.currentSettings) {\r\n Object.assign(this.currentSettings, partial);\r\n }\r\n this.callbacks.onChange(partial);\r\n }\r\n\r\n private section(title?: string): HTMLDivElement {\r\n const div = document.createElement('div');\r\n div.className = 'tcw-settings-section';\r\n if (title) {\r\n const t = document.createElement('div');\r\n t.className = 'tcw-settings-section-title';\r\n t.textContent = title;\r\n div.appendChild(t);\r\n }\r\n return div;\r\n }\r\n\r\n private colorRow(label: string, value: string, onChange: (v: string) => void): HTMLDivElement {\r\n const row = document.createElement('div');\r\n row.className = 'tcw-settings-row';\r\n\r\n const lbl = document.createElement('span');\r\n lbl.className = 'tcw-settings-label';\r\n lbl.textContent = label;\r\n row.appendChild(lbl);\r\n\r\n const wrap = document.createElement('div');\r\n wrap.className = 'tcw-color-picker-wrap';\r\n\r\n const input = document.createElement('input');\r\n input.type = 'color';\r\n input.value = value;\r\n\r\n const hex = document.createElement('span');\r\n hex.className = 'tcw-color-hex';\r\n hex.textContent = value;\r\n\r\n input.addEventListener('input', () => {\r\n hex.textContent = input.value;\r\n onChange(input.value);\r\n });\r\n\r\n wrap.appendChild(input);\r\n wrap.appendChild(hex);\r\n row.appendChild(wrap);\r\n return row;\r\n }\r\n\r\n private toggleRow(label: string, value: boolean, onChange: (v: boolean) => void): HTMLDivElement {\r\n const row = document.createElement('div');\r\n row.className = 'tcw-settings-row';\r\n\r\n const lbl = document.createElement('span');\r\n lbl.className = 'tcw-settings-label';\r\n lbl.textContent = label;\r\n row.appendChild(lbl);\r\n\r\n const toggle = document.createElement('button');\r\n toggle.className = `tcw-toggle${value ? ' tcw-on' : ''}`;\r\n toggle.addEventListener('click', () => {\r\n const newVal = !toggle.classList.contains('tcw-on');\r\n toggle.classList.toggle('tcw-on', newVal);\r\n onChange(newVal);\r\n });\r\n row.appendChild(toggle);\r\n return row;\r\n }\r\n\r\n private selectRow(\r\n label: string,\r\n value: string,\r\n options: { label: string; value: string }[],\r\n onChange: (v: string) => void,\r\n ): HTMLDivElement {\r\n const row = document.createElement('div');\r\n row.className = 'tcw-settings-row';\r\n\r\n const lbl = document.createElement('span');\r\n lbl.className = 'tcw-settings-label';\r\n lbl.textContent = label;\r\n row.appendChild(lbl);\r\n\r\n const select = document.createElement('select');\r\n select.className = 'tcw-settings-select';\r\n for (const opt of options) {\r\n const o = document.createElement('option');\r\n o.value = opt.value;\r\n o.textContent = opt.label;\r\n if (opt.value === value) o.selected = true;\r\n select.appendChild(o);\r\n }\r\n select.addEventListener('change', () => onChange(select.value));\r\n row.appendChild(select);\r\n return row;\r\n }\r\n\r\n private rangeRow(\r\n label: string,\r\n value: number,\r\n min: number,\r\n max: number,\r\n step: number,\r\n onChange: (v: number) => void,\r\n format: (v: number) => string = (v) => String(v),\r\n ): HTMLDivElement {\r\n const row = document.createElement('div');\r\n row.className = 'tcw-settings-row';\r\n\r\n const lbl = document.createElement('span');\r\n lbl.className = 'tcw-settings-label';\r\n lbl.textContent = label;\r\n row.appendChild(lbl);\r\n\r\n const wrap = document.createElement('div');\r\n wrap.className = 'tcw-settings-range';\r\n\r\n const input = document.createElement('input');\r\n input.type = 'range';\r\n input.min = String(min);\r\n input.max = String(max);\r\n input.step = String(step);\r\n input.value = String(value);\r\n\r\n const out = document.createElement('span');\r\n out.className = 'tcw-settings-range-val';\r\n out.textContent = format(value);\r\n\r\n input.addEventListener('input', () => {\r\n const v = Number(input.value);\r\n out.textContent = format(v);\r\n onChange(v);\r\n });\r\n\r\n wrap.appendChild(input);\r\n wrap.appendChild(out);\r\n row.appendChild(wrap);\r\n return row;\r\n }\r\n\r\n destroy(): void {\r\n this.close();\r\n }\r\n}\r\n","export class WidgetStatusBar {\r\n private el: HTMLDivElement;\r\n private dotEl: HTMLSpanElement;\r\n private messageEl: HTMLSpanElement;\r\n private infoEl: HTMLSpanElement;\r\n\r\n constructor(host: HTMLElement) {\r\n this.el = document.createElement('div');\r\n this.el.className = 'tcw-statusbar';\r\n\r\n const indicator = document.createElement('div');\r\n indicator.className = 'tcw-status-indicator';\r\n\r\n this.dotEl = document.createElement('span');\r\n this.dotEl.className = 'tcw-status-dot';\r\n indicator.appendChild(this.dotEl);\r\n\r\n this.messageEl = document.createElement('span');\r\n indicator.appendChild(this.messageEl);\r\n\r\n this.el.appendChild(indicator);\r\n\r\n this.infoEl = document.createElement('span');\r\n this.el.appendChild(this.infoEl);\r\n\r\n host.appendChild(this.el);\r\n }\r\n\r\n update(state: { connectionState: string; message: string; symbol: string; timeframe: string }): void {\r\n this.dotEl.className = 'tcw-status-dot';\r\n if (state.connectionState === 'connected') {\r\n this.dotEl.classList.add('tcw-connected');\r\n } else if (state.connectionState === 'error') {\r\n this.dotEl.classList.add('tcw-error');\r\n }\r\n\r\n this.messageEl.textContent = state.message;\r\n this.infoEl.textContent = `${state.symbol} ${state.timeframe}`;\r\n }\r\n\r\n destroy(): void {\r\n this.el.remove();\r\n }\r\n}\r\n","import type { ChartType, DrawingToolType, TimeFrame } from '@tradecanvas/commons';\r\n\r\nexport interface CommandItem {\r\n id: string;\r\n label: string;\r\n category: 'indicator' | 'chartType' | 'drawing' | 'timeframe' | 'action';\r\n shortcut?: string;\r\n active?: boolean;\r\n}\r\n\r\nexport interface CommandPaletteCallbacks {\r\n onIndicator: (id: string) => void;\r\n onChartType: (type: ChartType) => void;\r\n onDrawingTool: (tool: DrawingToolType) => void;\r\n onTimeframe: (tf: TimeFrame) => void;\r\n onAction: (id: string) => void;\r\n onClose: () => void;\r\n}\r\n\r\nexport class WidgetCommandPalette {\r\n private backdrop: HTMLDivElement | null = null;\r\n private modal: HTMLDivElement | null = null;\r\n private input: HTMLInputElement | null = null;\r\n private list: HTMLDivElement | null = null;\r\n private items: CommandItem[] = [];\r\n private filtered: CommandItem[] = [];\r\n private selectedIndex = 0;\r\n private callbacks: CommandPaletteCallbacks;\r\n private boundKeydown: (e: KeyboardEvent) => void;\r\n\r\n constructor(callbacks: CommandPaletteCallbacks) {\r\n this.callbacks = callbacks;\r\n this.boundKeydown = this.handleKeydown.bind(this);\r\n }\r\n\r\n open(items: CommandItem[]): void {\r\n if (this.backdrop) return;\r\n this.items = items;\r\n this.filtered = items;\r\n this.selectedIndex = 0;\r\n\r\n this.backdrop = document.createElement('div');\r\n this.backdrop.className = 'tcw-modal-backdrop';\r\n this.backdrop.addEventListener('click', () => this.close());\r\n\r\n this.modal = document.createElement('div');\r\n this.modal.className = 'tcw-cmd-palette';\r\n\r\n const header = document.createElement('div');\r\n header.className = 'tcw-cmd-header';\r\n\r\n const searchIcon = document.createElement('span');\r\n searchIcon.className = 'tcw-cmd-icon';\r\n searchIcon.textContent = '⌕';\r\n header.appendChild(searchIcon);\r\n\r\n this.input = document.createElement('input');\r\n this.input.className = 'tcw-cmd-input';\r\n this.input.type = 'text';\r\n this.input.placeholder = 'Search indicators, chart types, tools...';\r\n this.input.addEventListener('input', () => this.filter());\r\n header.appendChild(this.input);\r\n\r\n const hint = document.createElement('span');\r\n hint.className = 'tcw-cmd-hint';\r\n hint.textContent = 'ESC';\r\n header.appendChild(hint);\r\n\r\n this.modal.appendChild(header);\r\n\r\n this.list = document.createElement('div');\r\n this.list.className = 'tcw-cmd-list';\r\n this.modal.appendChild(this.list);\r\n\r\n const footer = document.createElement('div');\r\n footer.className = 'tcw-cmd-footer';\r\n footer.innerHTML = '<span>↑↓ Navigate</span><span>⏎ Select</span><span>Esc Close</span>';\r\n this.modal.appendChild(footer);\r\n\r\n document.body.appendChild(this.backdrop);\r\n document.body.appendChild(this.modal);\r\n\r\n this.renderList();\r\n this.input.focus();\r\n document.addEventListener('keydown', this.boundKeydown);\r\n }\r\n\r\n close(): void {\r\n document.removeEventListener('keydown', this.boundKeydown);\r\n this.backdrop?.remove();\r\n this.modal?.remove();\r\n this.backdrop = null;\r\n this.modal = null;\r\n this.input = null;\r\n this.list = null;\r\n this.callbacks.onClose();\r\n }\r\n\r\n isOpen(): boolean {\r\n return this.backdrop !== null;\r\n }\r\n\r\n private filter(): void {\r\n const query = this.input?.value.toLowerCase().trim() ?? '';\r\n if (!query) {\r\n this.filtered = this.items;\r\n } else {\r\n this.filtered = this.items.filter(item =>\r\n item.label.toLowerCase().includes(query) ||\r\n item.category.toLowerCase().includes(query) ||\r\n item.id.toLowerCase().includes(query),\r\n );\r\n }\r\n this.selectedIndex = 0;\r\n this.renderList();\r\n }\r\n\r\n private renderList(): void {\r\n if (!this.list) return;\r\n this.list.innerHTML = '';\r\n\r\n if (this.filtered.length === 0) {\r\n const empty = document.createElement('div');\r\n empty.className = 'tcw-cmd-empty';\r\n empty.textContent = 'No results found';\r\n this.list.appendChild(empty);\r\n return;\r\n }\r\n\r\n let currentCategory = '';\r\n for (let i = 0; i < this.filtered.length; i++) {\r\n const item = this.filtered[i];\r\n\r\n if (item.category !== currentCategory) {\r\n currentCategory = item.category;\r\n const label = document.createElement('div');\r\n label.className = 'tcw-cmd-category';\r\n label.textContent = this.categoryLabel(currentCategory);\r\n this.list.appendChild(label);\r\n }\r\n\r\n const row = document.createElement('button');\r\n row.className = 'tcw-cmd-item';\r\n if (i === this.selectedIndex) row.classList.add('tcw-selected');\r\n if (item.active) row.classList.add('tcw-active');\r\n row.dataset.index = String(i);\r\n\r\n const nameSpan = document.createElement('span');\r\n nameSpan.className = 'tcw-cmd-item-label';\r\n nameSpan.textContent = item.label;\r\n row.appendChild(nameSpan);\r\n\r\n if (item.active) {\r\n const check = document.createElement('span');\r\n check.className = 'tcw-cmd-check';\r\n check.textContent = '✓';\r\n row.appendChild(check);\r\n }\r\n\r\n if (item.shortcut) {\r\n const kbd = document.createElement('kbd');\r\n kbd.className = 'tcw-cmd-kbd';\r\n kbd.textContent = item.shortcut;\r\n row.appendChild(kbd);\r\n }\r\n\r\n row.addEventListener('click', () => this.select(i));\r\n row.addEventListener('mouseenter', () => {\r\n this.selectedIndex = i;\r\n this.updateSelection();\r\n });\r\n\r\n this.list.appendChild(row);\r\n }\r\n }\r\n\r\n private updateSelection(): void {\r\n if (!this.list) return;\r\n const items = this.list.querySelectorAll('.tcw-cmd-item');\r\n items.forEach((el, i) => {\r\n el.classList.toggle('tcw-selected', i === this.selectedIndex);\r\n });\r\n items[this.selectedIndex]?.scrollIntoView({ block: 'nearest' });\r\n }\r\n\r\n private select(index: number): void {\r\n const item = this.filtered[index];\r\n if (!item) return;\r\n\r\n switch (item.category) {\r\n case 'indicator':\r\n this.callbacks.onIndicator(item.id);\r\n break;\r\n case 'chartType':\r\n this.callbacks.onChartType(item.id as ChartType);\r\n break;\r\n case 'drawing':\r\n this.callbacks.onDrawingTool(item.id as DrawingToolType);\r\n break;\r\n case 'timeframe':\r\n this.callbacks.onTimeframe(item.id as TimeFrame);\r\n break;\r\n case 'action':\r\n this.callbacks.onAction(item.id);\r\n break;\r\n }\r\n this.close();\r\n }\r\n\r\n private handleKeydown(e: KeyboardEvent): void {\r\n switch (e.key) {\r\n case 'Escape':\r\n e.preventDefault();\r\n this.close();\r\n break;\r\n case 'ArrowDown':\r\n e.preventDefault();\r\n if (this.filtered.length > 0) {\r\n this.selectedIndex = (this.selectedIndex + 1) % this.filtered.length;\r\n this.updateSelection();\r\n }\r\n break;\r\n case 'ArrowUp':\r\n e.preventDefault();\r\n if (this.filtered.length > 0) {\r\n this.selectedIndex = (this.selectedIndex - 1 + this.filtered.length) % this.filtered.length;\r\n this.updateSelection();\r\n }\r\n break;\r\n case 'Enter':\r\n e.preventDefault();\r\n this.select(this.selectedIndex);\r\n break;\r\n }\r\n }\r\n\r\n private categoryLabel(cat: string): string {\r\n switch (cat) {\r\n case 'indicator': return 'Indicators';\r\n case 'chartType': return 'Chart Types';\r\n case 'drawing': return 'Drawing Tools';\r\n case 'timeframe': return 'Timeframes';\r\n case 'action': return 'Actions';\r\n default: return cat;\r\n }\r\n }\r\n\r\n destroy(): void {\r\n this.close();\r\n }\r\n}\r\n","/**\r\n * Lightweight fuzzy symbol picker. Reuses the command-palette CSS for visual\r\n * consistency. Scoring is a cheap subsequence match — good enough for symbol\r\n * lists in the low thousands without pulling in a fuzzy-search dependency.\r\n */\r\nexport interface SymbolSearchCallbacks {\r\n onPick: (symbol: string) => void;\r\n onClose: () => void;\r\n}\r\n\r\ninterface ScoredSymbol {\r\n symbol: string;\r\n score: number;\r\n}\r\n\r\nexport class WidgetSymbolSearch {\r\n private backdrop: HTMLDivElement | null = null;\r\n private modal: HTMLDivElement | null = null;\r\n private input: HTMLInputElement | null = null;\r\n private list: HTMLDivElement | null = null;\r\n private symbols: string[] = [];\r\n private current: string = '';\r\n private filtered: ScoredSymbol[] = [];\r\n private selectedIndex = 0;\r\n private callbacks: SymbolSearchCallbacks;\r\n private boundKeydown: (e: KeyboardEvent) => void;\r\n /** One-shot pick override — when set, this open() routes picks here instead. */\r\n private pickOverride: ((symbol: string) => void) | null = null;\r\n\r\n constructor(callbacks: SymbolSearchCallbacks) {\r\n this.callbacks = callbacks;\r\n this.boundKeydown = this.handleKeydown.bind(this);\r\n }\r\n\r\n open(symbols: string[], current: string, onPick?: (symbol: string) => void): void {\r\n if (this.backdrop) return;\r\n this.pickOverride = onPick ?? null;\r\n this.symbols = symbols;\r\n this.current = current;\r\n this.filtered = symbols.map(s => ({ symbol: s, score: 0 }));\r\n this.selectedIndex = Math.max(0, symbols.indexOf(current));\r\n\r\n this.backdrop = document.createElement('div');\r\n this.backdrop.className = 'tcw-modal-backdrop';\r\n this.backdrop.addEventListener('click', () => this.close());\r\n\r\n this.modal = document.createElement('div');\r\n this.modal.className = 'tcw-cmd-palette';\r\n\r\n const header = document.createElement('div');\r\n header.className = 'tcw-cmd-header';\r\n\r\n const icon = document.createElement('span');\r\n icon.className = 'tcw-cmd-icon';\r\n icon.innerHTML = svgSearch();\r\n header.appendChild(icon);\r\n\r\n this.input = document.createElement('input');\r\n this.input.className = 'tcw-cmd-input';\r\n this.input.type = 'text';\r\n this.input.placeholder = 'Search symbol… (e.g. BTC, ETH, AAPL)';\r\n this.input.autocomplete = 'off';\r\n this.input.spellcheck = false;\r\n this.input.addEventListener('input', () => this.filter());\r\n header.appendChild(this.input);\r\n\r\n const hint = document.createElement('span');\r\n hint.className = 'tcw-cmd-hint';\r\n hint.textContent = 'ESC';\r\n header.appendChild(hint);\r\n\r\n this.modal.appendChild(header);\r\n\r\n this.list = document.createElement('div');\r\n this.list.className = 'tcw-cmd-list';\r\n this.modal.appendChild(this.list);\r\n\r\n const footer = document.createElement('div');\r\n footer.className = 'tcw-cmd-footer';\r\n footer.innerHTML = '<span>↑↓ Navigate</span><span>⏎ Open</span><span>Esc Close</span>';\r\n this.modal.appendChild(footer);\r\n\r\n document.body.appendChild(this.backdrop);\r\n document.body.appendChild(this.modal);\r\n\r\n this.renderList();\r\n this.input.focus();\r\n document.addEventListener('keydown', this.boundKeydown);\r\n }\r\n\r\n close(): void {\r\n document.removeEventListener('keydown', this.boundKeydown);\r\n this.backdrop?.remove();\r\n this.modal?.remove();\r\n this.backdrop = null;\r\n this.modal = null;\r\n this.input = null;\r\n this.list = null;\r\n this.pickOverride = null;\r\n this.callbacks.onClose();\r\n }\r\n\r\n isOpen(): boolean {\r\n return this.backdrop !== null;\r\n }\r\n\r\n destroy(): void {\r\n this.close();\r\n }\r\n\r\n private filter(): void {\r\n const q = (this.input?.value ?? '').toUpperCase().trim();\r\n if (!q) {\r\n this.filtered = this.symbols.map(s => ({ symbol: s, score: 0 }));\r\n } else {\r\n this.filtered = this.symbols\r\n .map(s => ({ symbol: s, score: scoreMatch(s.toUpperCase(), q) }))\r\n .filter(r => r.score > 0)\r\n .sort((a, b) => b.score - a.score);\r\n }\r\n this.selectedIndex = 0;\r\n this.renderList();\r\n }\r\n\r\n private renderList(): void {\r\n if (!this.list) return;\r\n this.list.innerHTML = '';\r\n\r\n if (this.filtered.length === 0) {\r\n const empty = document.createElement('div');\r\n empty.className = 'tcw-cmd-empty';\r\n empty.textContent = 'No symbols match';\r\n this.list.appendChild(empty);\r\n return;\r\n }\r\n\r\n const query = (this.input?.value ?? '').toUpperCase().trim();\r\n for (let i = 0; i < this.filtered.length; i++) {\r\n const { symbol } = this.filtered[i];\r\n const row = document.createElement('button');\r\n row.className = 'tcw-cmd-item';\r\n if (i === this.selectedIndex) row.classList.add('tcw-selected');\r\n if (symbol === this.current) row.classList.add('tcw-active');\r\n\r\n const label = document.createElement('span');\r\n label.className = 'tcw-cmd-item-label';\r\n label.innerHTML = highlight(symbol, query);\r\n row.appendChild(label);\r\n\r\n if (symbol === this.current) {\r\n const check = document.createElement('span');\r\n check.className = 'tcw-cmd-check';\r\n check.textContent = '✓';\r\n row.appendChild(check);\r\n }\r\n\r\n row.addEventListener('click', () => this.pick(i));\r\n row.addEventListener('mouseenter', () => {\r\n this.selectedIndex = i;\r\n this.updateSelection();\r\n });\r\n\r\n this.list.appendChild(row);\r\n }\r\n }\r\n\r\n private updateSelection(): void {\r\n if (!this.list) return;\r\n const items = this.list.querySelectorAll('.tcw-cmd-item');\r\n items.forEach((el, i) => el.classList.toggle('tcw-selected', i === this.selectedIndex));\r\n items[this.selectedIndex]?.scrollIntoView({ block: 'nearest' });\r\n }\r\n\r\n private pick(index: number): void {\r\n const entry = this.filtered[index];\r\n if (!entry) return;\r\n const override = this.pickOverride;\r\n if (override) override(entry.symbol);\r\n else this.callbacks.onPick(entry.symbol);\r\n this.close();\r\n }\r\n\r\n private handleKeydown(e: KeyboardEvent): void {\r\n switch (e.key) {\r\n case 'Escape':\r\n e.preventDefault();\r\n this.close();\r\n break;\r\n case 'ArrowDown':\r\n e.preventDefault();\r\n if (this.filtered.length > 0) {\r\n this.selectedIndex = (this.selectedIndex + 1) % this.filtered.length;\r\n this.updateSelection();\r\n }\r\n break;\r\n case 'ArrowUp':\r\n e.preventDefault();\r\n if (this.filtered.length > 0) {\r\n this.selectedIndex = (this.selectedIndex - 1 + this.filtered.length) % this.filtered.length;\r\n this.updateSelection();\r\n }\r\n break;\r\n case 'Enter':\r\n e.preventDefault();\r\n this.pick(this.selectedIndex);\r\n break;\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Cheap fuzzy score:\r\n * exact match → 1000\r\n * starts-with → 500 + tighter-prefix bonus\r\n * subsequence match → 100 − gap penalty\r\n * no match → 0\r\n */\r\nfunction scoreMatch(symbol: string, query: string): number {\r\n if (symbol === query) return 1000;\r\n if (symbol.startsWith(query)) return 500 + (50 - Math.min(50, symbol.length - query.length));\r\n if (symbol.includes(query)) return 200 + (50 - Math.min(50, symbol.length - query.length));\r\n\r\n let qi = 0;\r\n let lastIdx = -1;\r\n let gapPenalty = 0;\r\n for (let i = 0; i < symbol.length && qi < query.length; i++) {\r\n if (symbol[i] === query[qi]) {\r\n if (lastIdx >= 0) gapPenalty += i - lastIdx - 1;\r\n lastIdx = i;\r\n qi++;\r\n }\r\n }\r\n if (qi < query.length) return 0;\r\n return 100 - Math.min(99, gapPenalty);\r\n}\r\n\r\nfunction highlight(symbol: string, query: string): string {\r\n if (!query) return escapeHtml(symbol);\r\n const upper = symbol.toUpperCase();\r\n let out = '';\r\n let qi = 0;\r\n for (let i = 0; i < symbol.length; i++) {\r\n if (qi < query.length && upper[i] === query[qi]) {\r\n out += `<mark style=\"background:transparent;color:var(--tcw-accent);font-weight:700\">${escapeHtml(symbol[i])}</mark>`;\r\n qi++;\r\n } else {\r\n out += escapeHtml(symbol[i]);\r\n }\r\n }\r\n return out;\r\n}\r\n\r\nfunction escapeHtml(s: string): string {\r\n return s.replace(/[&<>\"']/g, ch => ({\r\n '&': '&amp;', '<': '&lt;', '>': '&gt;', '\"': '&quot;', \"'\": '&#39;',\r\n } as Record<string, string>)[ch]);\r\n}\r\n\r\nfunction svgSearch(): string {\r\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>';\r\n}\r\n","import type { MessageKey, Translator } from './i18n.js';\r\n\r\n/**\r\n * Keyboard-shortcut reference sheet. Bound to `?` (and `Shift+/`). Surfaces\r\n * shortcuts so users discover the widget's hidden interaction model — a\r\n * premium-feel detail TradingView, Linear, Figma, etc. all ship.\r\n */\r\nexport interface HotkeySheetCallbacks {\r\n onClose: () => void;\r\n}\r\n\r\n// Group titles translate via this lookup; individual shortcut labels (and\r\n// the `keys` badges) stay English for now — see README \"Widget i18n\".\r\nconst GROUP_TITLE_KEYS: Record<string, MessageKey> = {\r\n 'Search & navigation': 'hotkeys.group.searchNavigation',\r\n 'Chart manipulation': 'hotkeys.group.chartManipulation',\r\n 'Touch (mobile / tablet)': 'hotkeys.group.touch',\r\n 'Keyboard': 'hotkeys.group.keyboard',\r\n 'Drawing': 'hotkeys.group.drawing',\r\n};\r\n\r\ninterface HotkeyEntry {\r\n keys: string[];\r\n label: string;\r\n}\r\n\r\ninterface HotkeyGroup {\r\n title: string;\r\n entries: HotkeyEntry[];\r\n}\r\n\r\nconst isMac =\r\n typeof navigator !== 'undefined' && /mac|iphone|ipad|ipod/i.test(navigator.platform || navigator.userAgent);\r\nconst mod = isMac ? '⌘' : 'Ctrl';\r\n\r\nconst GROUPS: HotkeyGroup[] = [\r\n {\r\n title: 'Search & navigation',\r\n entries: [\r\n { keys: [mod, 'K'], label: 'Command palette' },\r\n { keys: [mod, 'P'], label: 'Symbol search' },\r\n { keys: ['?'], label: 'Show this sheet' },\r\n ],\r\n },\r\n {\r\n title: 'Chart manipulation',\r\n entries: [\r\n { keys: ['Shift', 'Drag'], label: 'Measure tool (bars × price Δ)' },\r\n { keys: ['Drag', 'Price axis'], label: 'Compress / expand vertical scale' },\r\n { keys: ['Drag', 'Time axis'], label: 'Zoom time axis' },\r\n { keys: ['Double-click', 'Price axis'], label: 'Re-enable auto-scale' },\r\n { keys: ['Double-click', 'Time axis'], label: 'Fit content' },\r\n { keys: ['Scroll'], label: 'Zoom around cursor' },\r\n ],\r\n },\r\n {\r\n title: 'Touch (mobile / tablet)',\r\n entries: [\r\n { keys: ['1 finger', 'Drag'], label: 'Pan / move crosshair' },\r\n { keys: ['2 fingers', 'Pinch'], label: 'Zoom around midpoint' },\r\n { keys: ['Long-press'], label: 'Pin OHLC tooltip at bar' },\r\n { keys: ['Drag', 'Axis strip'], label: 'Scale price / time axis' },\r\n ],\r\n },\r\n {\r\n title: 'Keyboard',\r\n entries: [\r\n { keys: ['←', '→'], label: 'Pan one bar' },\r\n { keys: ['+', '−'], label: 'Zoom in / out' },\r\n { keys: ['Home'], label: 'Scroll to start' },\r\n { keys: ['End'], label: 'Scroll to end (live edge)' },\r\n { keys: ['F'], label: 'Fit content' },\r\n ],\r\n },\r\n {\r\n title: 'Drawing',\r\n entries: [\r\n { keys: [mod, 'Z'], label: 'Undo' },\r\n { keys: [mod, 'Shift', 'Z'], label: 'Redo' },\r\n { keys: ['Esc'], label: 'Cancel active drawing' },\r\n ],\r\n },\r\n];\r\n\r\nexport class WidgetHotkeySheet {\r\n private backdrop: HTMLDivElement | null = null;\r\n private modal: HTMLDivElement | null = null;\r\n private callbacks: HotkeySheetCallbacks;\r\n private t: Translator;\r\n private boundKeydown: (e: KeyboardEvent) => void;\r\n\r\n constructor(callbacks: HotkeySheetCallbacks, t: Translator) {\r\n this.callbacks = callbacks;\r\n this.t = t;\r\n this.boundKeydown = (e) => {\r\n if (e.key === 'Escape') {\r\n e.preventDefault();\r\n this.close();\r\n }\r\n };\r\n }\r\n\r\n open(): void {\r\n if (this.backdrop) return;\r\n\r\n this.backdrop = document.createElement('div');\r\n this.backdrop.className = 'tcw-modal-backdrop';\r\n this.backdrop.addEventListener('click', () => this.close());\r\n\r\n this.modal = document.createElement('div');\r\n this.modal.className = 'tcw-modal tcw-hotkey-sheet';\r\n this.modal.style.width = '640px';\r\n\r\n const header = document.createElement('div');\r\n header.className = 'tcw-modal-header';\r\n header.innerHTML = `<h3>${this.t('hotkeys.title')}</h3>`;\r\n const closeBtn = document.createElement('button');\r\n closeBtn.className = 'tcw-modal-close';\r\n closeBtn.setAttribute('aria-label', this.t('hotkeys.close'));\r\n closeBtn.innerHTML = '×';\r\n closeBtn.addEventListener('click', () => this.close());\r\n header.appendChild(closeBtn);\r\n this.modal.appendChild(header);\r\n\r\n const body = document.createElement('div');\r\n body.className = 'tcw-modal-body';\r\n\r\n const grid = document.createElement('div');\r\n grid.className = 'tcw-hotkey-grid';\r\n\r\n for (const group of GROUPS) {\r\n const section = document.createElement('section');\r\n section.className = 'tcw-hotkey-section';\r\n const title = document.createElement('div');\r\n title.className = 'tcw-settings-section-title';\r\n const titleKey = GROUP_TITLE_KEYS[group.title];\r\n title.textContent = titleKey ? this.t(titleKey) : group.title;\r\n section.appendChild(title);\r\n\r\n for (const entry of group.entries) {\r\n const row = document.createElement('div');\r\n row.className = 'tcw-hotkey-row';\r\n\r\n const keys = document.createElement('div');\r\n keys.className = 'tcw-hotkey-keys';\r\n for (let i = 0; i < entry.keys.length; i++) {\r\n if (i > 0) {\r\n const plus = document.createElement('span');\r\n plus.className = 'tcw-hotkey-sep';\r\n plus.textContent = '+';\r\n keys.appendChild(plus);\r\n }\r\n const kbd = document.createElement('kbd');\r\n kbd.className = 'tcw-cmd-kbd';\r\n kbd.textContent = entry.keys[i];\r\n keys.appendChild(kbd);\r\n }\r\n row.appendChild(keys);\r\n\r\n const label = document.createElement('span');\r\n label.className = 'tcw-hotkey-label';\r\n label.textContent = entry.label;\r\n row.appendChild(label);\r\n\r\n section.appendChild(row);\r\n }\r\n\r\n grid.appendChild(section);\r\n }\r\n\r\n body.appendChild(grid);\r\n this.modal.appendChild(body);\r\n\r\n const footer = document.createElement('div');\r\n footer.className = 'tcw-modal-footer';\r\n footer.innerHTML = '<span style=\"font-size:11px;color:var(--tcw-text-muted)\">Press ? anytime to show this sheet</span>';\r\n const ok = document.createElement('button');\r\n ok.className = 'tcw-done-btn';\r\n ok.textContent = this.t('hotkeys.gotIt');\r\n ok.addEventListener('click', () => this.close());\r\n footer.appendChild(ok);\r\n this.modal.appendChild(footer);\r\n\r\n document.body.appendChild(this.backdrop);\r\n document.body.appendChild(this.modal);\r\n\r\n document.addEventListener('keydown', this.boundKeydown);\r\n }\r\n\r\n close(): void {\r\n document.removeEventListener('keydown', this.boundKeydown);\r\n this.backdrop?.remove();\r\n this.modal?.remove();\r\n this.backdrop = null;\r\n this.modal = null;\r\n this.callbacks.onClose();\r\n }\r\n\r\n isOpen(): boolean {\r\n return this.backdrop !== null;\r\n }\r\n\r\n destroy(): void {\r\n this.close();\r\n }\r\n}\r\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","/**\r\n * Watchlist sidebar — vertical list of symbols, each with last price, %\r\n * change, and a mini sparkline. Clicking switches the chart's symbol.\r\n *\r\n * The widget tracks the *active* symbol's price/spark automatically from the\r\n * live stream. For non-active symbols, the host can push data via\r\n * `setEntry(symbol, …)` so the row reflects whatever the app already has.\r\n */\r\nexport interface WatchlistEntry {\r\n symbol: string;\r\n lastPrice?: number;\r\n /** Reference price for % calc (usually session open or 24h-ago close). */\r\n refPrice?: number;\r\n /** Recent close samples for the sparkline — last point is the live price. */\r\n sparkline?: number[];\r\n}\r\n\r\nexport interface WatchlistCallbacks {\r\n onSelect: (symbol: string) => void;\r\n}\r\n\r\nexport class WidgetWatchlist {\r\n private el: HTMLDivElement;\r\n private listEl: HTMLDivElement;\r\n private rowMap = new Map<string, {\r\n row: HTMLDivElement;\r\n priceEl: HTMLSpanElement;\r\n changeEl: HTMLSpanElement;\r\n sparkCanvas: HTMLCanvasElement;\r\n }>();\r\n private entries = new Map<string, WatchlistEntry>();\r\n private active: string | null = null;\r\n private callbacks: WatchlistCallbacks;\r\n private locale: string | undefined;\r\n\r\n constructor(host: HTMLElement, symbols: string[], callbacks: WatchlistCallbacks, title = 'Watchlist') {\r\n this.callbacks = callbacks;\r\n\r\n this.el = document.createElement('div');\r\n this.el.className = 'tcw-watchlist';\r\n\r\n const header = document.createElement('div');\r\n header.className = 'tcw-watchlist-header';\r\n header.textContent = title;\r\n this.el.appendChild(header);\r\n\r\n this.listEl = document.createElement('div');\r\n this.listEl.className = 'tcw-watchlist-list';\r\n this.el.appendChild(this.listEl);\r\n\r\n for (const symbol of symbols) {\r\n this.entries.set(symbol, { symbol });\r\n this.appendRow(symbol);\r\n }\r\n\r\n host.appendChild(this.el);\r\n }\r\n\r\n /** Set the BCP 47 locale used for price/percent formatting. */\r\n setLocale(locale: string | undefined): void {\r\n this.locale = locale;\r\n for (const symbol of this.entries.keys()) this.renderRow(symbol);\r\n }\r\n\r\n /** Replace the symbol set. Rows are diff'd so DOM churn is minimal. */\r\n setSymbols(symbols: string[]): void {\r\n const next = new Set(symbols);\r\n for (const sym of this.rowMap.keys()) {\r\n if (!next.has(sym)) this.removeRow(sym);\r\n }\r\n for (const sym of symbols) {\r\n if (!this.rowMap.has(sym)) {\r\n this.entries.set(sym, this.entries.get(sym) ?? { symbol: sym });\r\n this.appendRow(sym);\r\n }\r\n }\r\n }\r\n\r\n setActive(symbol: string): void {\r\n if (this.active === symbol) return;\r\n if (this.active && this.rowMap.has(this.active)) {\r\n this.rowMap.get(this.active)!.row.classList.remove('tcw-watchlist-active');\r\n }\r\n this.active = symbol;\r\n const cur = this.rowMap.get(symbol);\r\n if (cur) cur.row.classList.add('tcw-watchlist-active');\r\n }\r\n\r\n /** Push a price tick into a row. The widget calls this automatically for\r\n * the active symbol. Apps can call it for the rest. */\r\n setEntry(symbol: string, patch: Partial<WatchlistEntry>): void {\r\n const prev = this.entries.get(symbol) ?? { symbol };\r\n const next = { ...prev, ...patch };\r\n this.entries.set(symbol, next);\r\n this.renderRow(symbol);\r\n }\r\n\r\n destroy(): void {\r\n this.el.remove();\r\n this.rowMap.clear();\r\n this.entries.clear();\r\n }\r\n\r\n private appendRow(symbol: string): void {\r\n const row = document.createElement('div');\r\n row.className = 'tcw-watchlist-row';\r\n row.tabIndex = 0;\r\n\r\n const label = document.createElement('div');\r\n label.className = 'tcw-watchlist-symbol';\r\n label.textContent = formatSymbol(symbol);\r\n\r\n const spark = document.createElement('canvas');\r\n spark.className = 'tcw-watchlist-spark';\r\n spark.width = 64;\r\n spark.height = 22;\r\n\r\n const right = document.createElement('div');\r\n right.className = 'tcw-watchlist-stats';\r\n const priceEl = document.createElement('span');\r\n priceEl.className = 'tcw-watchlist-price';\r\n priceEl.textContent = '—';\r\n const changeEl = document.createElement('span');\r\n changeEl.className = 'tcw-watchlist-change';\r\n changeEl.textContent = '';\r\n right.appendChild(priceEl);\r\n right.appendChild(changeEl);\r\n\r\n row.appendChild(label);\r\n row.appendChild(spark);\r\n row.appendChild(right);\r\n\r\n row.addEventListener('click', () => this.callbacks.onSelect(symbol));\r\n row.addEventListener('keydown', (e) => {\r\n if (e.key === 'Enter' || e.key === ' ') {\r\n e.preventDefault();\r\n this.callbacks.onSelect(symbol);\r\n }\r\n });\r\n\r\n this.listEl.appendChild(row);\r\n this.rowMap.set(symbol, { row, priceEl, changeEl, sparkCanvas: spark });\r\n if (symbol === this.active) row.classList.add('tcw-watchlist-active');\r\n }\r\n\r\n private removeRow(symbol: string): void {\r\n const ref = this.rowMap.get(symbol);\r\n if (!ref) return;\r\n ref.row.remove();\r\n this.rowMap.delete(symbol);\r\n }\r\n\r\n private renderRow(symbol: string): void {\r\n const ref = this.rowMap.get(symbol);\r\n const entry = this.entries.get(symbol);\r\n if (!ref || !entry) return;\r\n\r\n if (entry.lastPrice !== undefined) {\r\n ref.priceEl.textContent = formatPrice(entry.lastPrice, this.locale);\r\n }\r\n\r\n if (entry.lastPrice !== undefined && entry.refPrice !== undefined && entry.refPrice !== 0) {\r\n const diff = entry.lastPrice - entry.refPrice;\r\n const pct = (diff / entry.refPrice) * 100;\r\n const sign = diff >= 0 ? '+' : '-';\r\n const pctText = Math.abs(pct).toLocaleString(this.locale, { minimumFractionDigits: 2, maximumFractionDigits: 2 });\r\n ref.changeEl.textContent = `${sign}${pctText}%`;\r\n ref.changeEl.className = `tcw-watchlist-change ${diff >= 0 ? 'tcw-up' : 'tcw-down'}`;\r\n } else {\r\n ref.changeEl.textContent = '';\r\n }\r\n\r\n if (entry.sparkline && entry.sparkline.length >= 2) {\r\n drawSparkline(ref.sparkCanvas, entry.sparkline, entry.refPrice ?? entry.sparkline[0]);\r\n }\r\n }\r\n}\r\n\r\nfunction formatSymbol(symbol: string): string {\r\n // Add a / separator for typical crypto pair suffixes; leaves stock tickers\r\n // (AAPL, NVDA) alone.\r\n for (const quote of ['USDT', 'USD', 'BTC', 'ETH', 'EUR']) {\r\n if (symbol.length > quote.length && symbol.endsWith(quote)) {\r\n return symbol.slice(0, -quote.length) + '/' + quote;\r\n }\r\n }\r\n return symbol;\r\n}\r\n\r\nfunction formatPrice(v: number, locale: string | undefined): string {\r\n if (v === 0) return '0';\r\n const abs = Math.abs(v);\r\n if (abs >= 1000) return v.toLocaleString(locale, { minimumFractionDigits: 2, maximumFractionDigits: 2 });\r\n if (abs >= 1) return v.toLocaleString(locale, { minimumFractionDigits: 4, maximumFractionDigits: 4 });\r\n // toPrecision(4) has no locale-aware equivalent via toLocaleString (it\r\n // targets significant digits, not decimal places) — reformat its raw\r\n // fixed-notation output through Number.toLocaleString for the separator.\r\n const precise = Number(v.toPrecision(4));\r\n return precise.toLocaleString(locale, { maximumFractionDigits: 10 });\r\n}\r\n\r\nfunction drawSparkline(canvas: HTMLCanvasElement, samples: number[], ref: number): void {\r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) return;\r\n const dpr = window.devicePixelRatio || 1;\r\n if (canvas.width !== canvas.clientWidth * dpr) {\r\n canvas.width = (canvas.clientWidth || 64) * dpr;\r\n canvas.height = (canvas.clientHeight || 22) * dpr;\r\n }\r\n const w = canvas.width;\r\n const h = canvas.height;\r\n\r\n let lo = Infinity, hi = -Infinity;\r\n for (const v of samples) {\r\n if (v < lo) lo = v;\r\n if (v > hi) hi = v;\r\n }\r\n const span = Math.max(hi - lo, 1e-9);\r\n const last = samples[samples.length - 1];\r\n const up = last >= ref;\r\n const color = up ? '#26a17b' : '#f23645';\r\n\r\n ctx.clearRect(0, 0, w, h);\r\n ctx.lineWidth = 1.4 * dpr;\r\n ctx.strokeStyle = color;\r\n ctx.beginPath();\r\n const step = w / (samples.length - 1);\r\n for (let i = 0; i < samples.length; i++) {\r\n const x = i * step;\r\n const y = h - ((samples[i] - lo) / span) * (h - 4) - 2;\r\n if (i === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y);\r\n }\r\n ctx.stroke();\r\n}\r\n","import type { AlertCondition } from '@tradecanvas/core';\r\nimport { createIcon } from './icons.js';\r\n\r\nexport interface AlertListItem {\r\n id: string;\r\n price: number;\r\n condition: string;\r\n message?: string;\r\n triggered: boolean;\r\n channel?: string;\r\n label?: string;\r\n}\r\n\r\nexport interface AlertSource {\r\n /** `'price'` or `<instanceId>:<key>`. */\r\n channel: string;\r\n label: string;\r\n}\r\n\r\nexport interface AlertsPanelCallbacks {\r\n onAdd: (price: number, condition: AlertCondition, message: string | undefined, channel: string, label: string) => void;\r\n onRemove: (id: string) => void;\r\n onClear: () => void;\r\n /** Latest value for a source channel, used to prefill the add form. */\r\n getChannelValue: (channel: string) => number | null;\r\n formatPrice: (price: number) => string;\r\n}\r\n\r\nconst CONDITION_OPTIONS: { value: AlertCondition; label: string }[] = [\r\n { value: 'crossing', label: 'Crossing' },\r\n { value: 'crossingUp', label: 'Crossing up' },\r\n { value: 'crossingDown', label: 'Crossing down' },\r\n { value: 'greaterThan', label: 'Greater than' },\r\n { value: 'lessThan', label: 'Less than' },\r\n];\r\n\r\nconst CONDITION_LABEL = new Map(CONDITION_OPTIONS.map((o) => [o.value, o.label]));\r\n\r\nfunction roundForInput(v: number): number {\r\n return Math.round(v * 1e6) / 1e6;\r\n}\r\n\r\nfunction formatPlain(v: number): string {\r\n const abs = Math.abs(v);\r\n return abs >= 1000 ? v.toFixed(2) : abs >= 1 ? v.toFixed(2) : v.toPrecision(4);\r\n}\r\n\r\n/**\r\n * Floating price-alerts panel. Lists current alerts (with condition, price,\r\n * message, and a delete control) and an inline form to add a new one prefilled\r\n * with the current price. Toggled from the toolbar bell button; the host wires\r\n * add/remove back to the chart's `AlertManager`.\r\n */\r\nexport class WidgetAlertsPanel {\r\n private el: HTMLDivElement;\r\n private listEl: HTMLDivElement;\r\n private priceInput: HTMLInputElement;\r\n private conditionSelect: HTMLSelectElement;\r\n private sourceSelect: HTMLSelectElement;\r\n private messageInput: HTMLInputElement;\r\n private emptyEl: HTMLDivElement;\r\n private callbacks: AlertsPanelCallbacks;\r\n private open = false;\r\n private alerts: AlertListItem[] = [];\r\n private sources: AlertSource[] = [{ channel: 'price', label: 'Price' }];\r\n\r\n constructor(host: HTMLElement, callbacks: AlertsPanelCallbacks) {\r\n this.callbacks = callbacks;\r\n\r\n this.el = document.createElement('div');\r\n this.el.className = 'tcw-alerts-panel';\r\n this.el.hidden = true;\r\n\r\n // Header\r\n const header = document.createElement('div');\r\n header.className = 'tcw-alerts-header';\r\n const title = document.createElement('span');\r\n title.textContent = 'Price Alerts';\r\n const closeBtn = document.createElement('button');\r\n closeBtn.className = 'tcw-alerts-close';\r\n closeBtn.type = 'button';\r\n closeBtn.setAttribute('aria-label', 'Close alerts');\r\n closeBtn.innerHTML = createIcon('x', 14);\r\n closeBtn.addEventListener('click', () => this.close());\r\n header.appendChild(title);\r\n header.appendChild(closeBtn);\r\n this.el.appendChild(header);\r\n\r\n // Add form\r\n const form = document.createElement('form');\r\n form.className = 'tcw-alerts-form';\r\n\r\n this.sourceSelect = document.createElement('select');\r\n this.sourceSelect.className = 'tcw-alerts-source';\r\n this.sourceSelect.addEventListener('change', () => this.prefillPrice());\r\n\r\n this.priceInput = document.createElement('input');\r\n this.priceInput.type = 'number';\r\n this.priceInput.step = 'any';\r\n this.priceInput.placeholder = 'Value';\r\n this.priceInput.className = 'tcw-alerts-price';\r\n this.priceInput.required = true;\r\n\r\n this.conditionSelect = document.createElement('select');\r\n this.conditionSelect.className = 'tcw-alerts-condition';\r\n for (const opt of CONDITION_OPTIONS) {\r\n const o = document.createElement('option');\r\n o.value = opt.value;\r\n o.textContent = opt.label;\r\n this.conditionSelect.appendChild(o);\r\n }\r\n\r\n this.messageInput = document.createElement('input');\r\n this.messageInput.type = 'text';\r\n this.messageInput.placeholder = 'Note (optional)';\r\n this.messageInput.className = 'tcw-alerts-message';\r\n\r\n const addBtn = document.createElement('button');\r\n addBtn.type = 'submit';\r\n addBtn.className = 'tcw-alerts-add';\r\n addBtn.innerHTML = `${createIcon('plus', 14)}<span>Add alert</span>`;\r\n\r\n form.appendChild(this.sourceSelect);\r\n form.appendChild(this.priceInput);\r\n form.appendChild(this.conditionSelect);\r\n form.appendChild(this.messageInput);\r\n form.appendChild(addBtn);\r\n form.addEventListener('submit', (e) => {\r\n e.preventDefault();\r\n this.submitForm();\r\n });\r\n this.el.appendChild(form);\r\n\r\n // List\r\n this.listEl = document.createElement('div');\r\n this.listEl.className = 'tcw-alerts-list';\r\n this.el.appendChild(this.listEl);\r\n\r\n this.emptyEl = document.createElement('div');\r\n this.emptyEl.className = 'tcw-alerts-empty';\r\n this.emptyEl.textContent = 'No alerts yet. Add one above, or right-click the chart.';\r\n this.listEl.appendChild(this.emptyEl);\r\n\r\n this.renderSources();\r\n host.appendChild(this.el);\r\n }\r\n\r\n /** Replace the alert-source options (price + indicator lines). */\r\n setSources(sources: AlertSource[]): void {\r\n this.sources = sources.length > 0 ? sources : [{ channel: 'price', label: 'Price' }];\r\n this.renderSources();\r\n }\r\n\r\n private renderSources(): void {\r\n const current = this.sourceSelect.value || 'price';\r\n this.sourceSelect.replaceChildren();\r\n for (const src of this.sources) {\r\n const o = document.createElement('option');\r\n o.value = src.channel;\r\n o.textContent = src.label;\r\n this.sourceSelect.appendChild(o);\r\n }\r\n // Keep the prior selection if it still exists, else default to price.\r\n this.sourceSelect.value = this.sources.some((s) => s.channel === current) ? current : 'price';\r\n }\r\n\r\n isOpen(): boolean {\r\n return this.open;\r\n }\r\n\r\n toggle(): void {\r\n this.open ? this.close() : this.openPanel();\r\n }\r\n\r\n openPanel(): void {\r\n this.open = true;\r\n this.el.hidden = false;\r\n if (this.priceInput.value === '') this.prefillPrice();\r\n }\r\n\r\n /** Fill the value input with the selected source's current value. */\r\n private prefillPrice(): void {\r\n const v = this.callbacks.getChannelValue(this.sourceSelect.value || 'price');\r\n this.priceInput.value = v !== null ? String(roundForInput(v)) : '';\r\n }\r\n\r\n close(): void {\r\n this.open = false;\r\n this.el.hidden = true;\r\n }\r\n\r\n /** Replace the displayed alert list. */\r\n setAlerts(alerts: AlertListItem[]): void {\r\n this.alerts = alerts;\r\n this.renderList();\r\n }\r\n\r\n destroy(): void {\r\n this.el.remove();\r\n }\r\n\r\n private submitForm(): void {\r\n const price = Number(this.priceInput.value);\r\n if (!Number.isFinite(price)) return;\r\n const condition = this.conditionSelect.value as AlertCondition;\r\n const message = this.messageInput.value.trim() || undefined;\r\n const channel = this.sourceSelect.value || 'price';\r\n const label = this.sources.find((s) => s.channel === channel)?.label ?? 'Price';\r\n this.callbacks.onAdd(price, condition, message, channel, label);\r\n this.messageInput.value = '';\r\n this.prefillPrice();\r\n }\r\n\r\n private renderList(): void {\r\n // Clear rows but keep the empty placeholder reference.\r\n this.listEl.replaceChildren();\r\n\r\n if (this.alerts.length === 0) {\r\n this.listEl.appendChild(this.emptyEl);\r\n return;\r\n }\r\n\r\n // Show most recent first.\r\n for (const alert of [...this.alerts].reverse()) {\r\n const row = document.createElement('div');\r\n row.className = 'tcw-alerts-row' + (alert.triggered ? ' tcw-alerts-triggered' : '');\r\n\r\n const info = document.createElement('div');\r\n info.className = 'tcw-alerts-info';\r\n const main = document.createElement('div');\r\n main.className = 'tcw-alerts-row-main';\r\n const label = CONDITION_LABEL.get(alert.condition as AlertCondition) ?? alert.condition;\r\n const isIndicator = alert.channel && alert.channel !== 'price';\r\n const valueStr = isIndicator ? formatPlain(alert.price) : this.callbacks.formatPrice(alert.price);\r\n const prefix = isIndicator && alert.label ? `${alert.label} ` : '';\r\n main.textContent = `${prefix}${label} ${valueStr}`;\r\n info.appendChild(main);\r\n if (alert.message) {\r\n const note = document.createElement('div');\r\n note.className = 'tcw-alerts-row-note';\r\n note.textContent = alert.message;\r\n info.appendChild(note);\r\n }\r\n if (alert.triggered) {\r\n const badge = document.createElement('span');\r\n badge.className = 'tcw-alerts-badge';\r\n badge.textContent = 'triggered';\r\n main.appendChild(badge);\r\n }\r\n\r\n const del = document.createElement('button');\r\n del.type = 'button';\r\n del.className = 'tcw-alerts-del';\r\n del.setAttribute('aria-label', 'Delete alert');\r\n del.innerHTML = createIcon('trash', 14);\r\n del.addEventListener('click', () => this.callbacks.onRemove(alert.id));\r\n\r\n row.appendChild(info);\r\n row.appendChild(del);\r\n this.listEl.appendChild(row);\r\n }\r\n }\r\n}\r\n","import { createIcon } from './icons.js';\r\n\r\nexport interface ObjectTreeIndicator {\r\n instanceId: string;\r\n name: string;\r\n visible: boolean;\r\n}\r\n\r\nexport interface ObjectTreeDrawing {\r\n id: string;\r\n label: string;\r\n visible: boolean;\r\n locked: boolean;\r\n}\r\n\r\nexport interface ObjectTreeCompare {\r\n id: string;\r\n label: string;\r\n color: string;\r\n}\r\n\r\nexport interface ObjectTreeCallbacks {\r\n onRemoveIndicator: (instanceId: string) => void;\r\n onConfigureIndicator?: (instanceId: string) => void;\r\n onToggleIndicatorVisible?: (instanceId: string, visible: boolean) => void;\r\n onRemoveDrawing: (id: string) => void;\r\n onToggleDrawingVisible: (id: string, visible: boolean) => void;\r\n onToggleDrawingLocked: (id: string, locked: boolean) => void;\r\n /** When provided, a Compare section with an \"add\" button is shown. */\r\n onAddCompare?: () => void;\r\n onRemoveCompare?: (id: string) => void;\r\n}\r\n\r\n/**\r\n * Object-tree panel — TradingView's layers manager. Lists every active\r\n * indicator and drawing on the chart with per-item controls: indicators can be\r\n * removed; drawings can be shown/hidden, locked/unlocked, and removed. Toggled\r\n * from the toolbar layers button; the host wires actions back to the chart.\r\n */\r\nexport class WidgetObjectTree {\r\n private el: HTMLDivElement;\r\n private indicatorsEl: HTMLDivElement;\r\n private drawingsEl: HTMLDivElement;\r\n private compareEl: HTMLDivElement | null = null;\r\n private callbacks: ObjectTreeCallbacks;\r\n private open = false;\r\n\r\n constructor(host: HTMLElement, callbacks: ObjectTreeCallbacks) {\r\n this.callbacks = callbacks;\r\n\r\n this.el = document.createElement('div');\r\n this.el.className = 'tcw-tree-panel';\r\n this.el.hidden = true;\r\n\r\n const header = document.createElement('div');\r\n header.className = 'tcw-tree-header';\r\n const title = document.createElement('span');\r\n title.textContent = 'Objects';\r\n const closeBtn = document.createElement('button');\r\n closeBtn.type = 'button';\r\n closeBtn.className = 'tcw-tree-close';\r\n closeBtn.setAttribute('aria-label', 'Close objects');\r\n closeBtn.innerHTML = createIcon('x', 14);\r\n closeBtn.addEventListener('click', () => this.close());\r\n header.appendChild(title);\r\n header.appendChild(closeBtn);\r\n this.el.appendChild(header);\r\n\r\n this.indicatorsEl = this.makeSection('Indicators');\r\n this.drawingsEl = this.makeSection('Drawings');\r\n if (this.callbacks.onAddCompare) {\r\n this.compareEl = this.makeSection('Compare', () => this.callbacks.onAddCompare?.());\r\n }\r\n\r\n host.appendChild(this.el);\r\n }\r\n\r\n isOpen(): boolean {\r\n return this.open;\r\n }\r\n\r\n toggle(): void {\r\n this.open ? this.close() : this.openPanel();\r\n }\r\n\r\n openPanel(): void {\r\n this.open = true;\r\n this.el.hidden = false;\r\n }\r\n\r\n close(): void {\r\n this.open = false;\r\n this.el.hidden = true;\r\n }\r\n\r\n destroy(): void {\r\n this.el.remove();\r\n }\r\n\r\n /** Replace all lists. Cheap full re-render — counts are small. */\r\n setObjects(\r\n indicators: ObjectTreeIndicator[],\r\n drawings: ObjectTreeDrawing[],\r\n compares: ObjectTreeCompare[] = [],\r\n ): void {\r\n this.renderIndicators(indicators);\r\n this.renderDrawings(drawings);\r\n this.renderCompares(compares);\r\n }\r\n\r\n private makeSection(title: string, onAdd?: () => void): HTMLDivElement {\r\n const wrap = document.createElement('div');\r\n wrap.className = 'tcw-tree-section';\r\n const head = document.createElement('div');\r\n head.className = 'tcw-tree-section-head';\r\n const label = document.createElement('span');\r\n label.textContent = title;\r\n head.appendChild(label);\r\n if (onAdd) {\r\n const addBtn = document.createElement('button');\r\n addBtn.type = 'button';\r\n addBtn.className = 'tcw-tree-add';\r\n addBtn.setAttribute('aria-label', `Add ${title.toLowerCase()}`);\r\n addBtn.title = `Add ${title.toLowerCase()}`;\r\n addBtn.innerHTML = createIcon('plus', 13);\r\n addBtn.addEventListener('click', onAdd);\r\n head.appendChild(addBtn);\r\n }\r\n const list = document.createElement('div');\r\n list.className = 'tcw-tree-list';\r\n wrap.appendChild(head);\r\n wrap.appendChild(list);\r\n this.el.appendChild(wrap);\r\n return list;\r\n }\r\n\r\n private renderIndicators(indicators: ObjectTreeIndicator[]): void {\r\n this.indicatorsEl.replaceChildren();\r\n if (indicators.length === 0) {\r\n this.indicatorsEl.appendChild(this.emptyRow('No indicators'));\r\n return;\r\n }\r\n for (const ind of indicators) {\r\n const row = this.row(ind.name);\r\n if (!ind.visible) row.classList.add('tcw-tree-hidden');\r\n const actions = document.createElement('div');\r\n actions.className = 'tcw-tree-actions';\r\n if (this.callbacks.onToggleIndicatorVisible) {\r\n actions.appendChild(this.iconButton(\r\n ind.visible ? 'eye' : 'eyeOff',\r\n ind.visible ? 'Hide' : 'Show',\r\n '',\r\n () => this.callbacks.onToggleIndicatorVisible?.(ind.instanceId, !ind.visible),\r\n ));\r\n }\r\n if (this.callbacks.onConfigureIndicator) {\r\n actions.appendChild(this.iconButton('settings', 'Indicator settings', '', () =>\r\n this.callbacks.onConfigureIndicator?.(ind.instanceId),\r\n ));\r\n }\r\n actions.appendChild(this.iconButton('trash', 'Remove indicator', 'tcw-tree-del', () =>\r\n this.callbacks.onRemoveIndicator(ind.instanceId),\r\n ));\r\n row.appendChild(actions);\r\n this.indicatorsEl.appendChild(row);\r\n }\r\n }\r\n\r\n private renderDrawings(drawings: ObjectTreeDrawing[]): void {\r\n this.drawingsEl.replaceChildren();\r\n if (drawings.length === 0) {\r\n this.drawingsEl.appendChild(this.emptyRow('No drawings'));\r\n return;\r\n }\r\n for (const d of drawings) {\r\n const row = this.row(d.label);\r\n if (!d.visible) row.classList.add('tcw-tree-hidden');\r\n\r\n const actions = document.createElement('div');\r\n actions.className = 'tcw-tree-actions';\r\n actions.appendChild(this.iconButton(\r\n d.visible ? 'eye' : 'eyeOff',\r\n d.visible ? 'Hide' : 'Show',\r\n '',\r\n () => this.callbacks.onToggleDrawingVisible(d.id, !d.visible),\r\n ));\r\n actions.appendChild(this.iconButton(\r\n d.locked ? 'lock' : 'unlock',\r\n d.locked ? 'Unlock' : 'Lock',\r\n d.locked ? 'tcw-tree-on' : '',\r\n () => this.callbacks.onToggleDrawingLocked(d.id, !d.locked),\r\n ));\r\n actions.appendChild(this.iconButton('trash', 'Remove drawing', 'tcw-tree-del', () =>\r\n this.callbacks.onRemoveDrawing(d.id),\r\n ));\r\n row.appendChild(actions);\r\n this.drawingsEl.appendChild(row);\r\n }\r\n }\r\n\r\n private renderCompares(compares: ObjectTreeCompare[]): void {\r\n if (!this.compareEl) return;\r\n this.compareEl.replaceChildren();\r\n if (compares.length === 0) {\r\n this.compareEl.appendChild(this.emptyRow('No comparisons'));\r\n return;\r\n }\r\n for (const c of compares) {\r\n const row = this.row(c.label);\r\n const dot = document.createElement('span');\r\n dot.className = 'tcw-tree-dot';\r\n dot.style.background = c.color;\r\n row.insertBefore(dot, row.firstChild);\r\n if (this.callbacks.onRemoveCompare) {\r\n row.appendChild(this.iconButton('trash', 'Remove comparison', 'tcw-tree-del', () =>\r\n this.callbacks.onRemoveCompare?.(c.id),\r\n ));\r\n }\r\n this.compareEl.appendChild(row);\r\n }\r\n }\r\n\r\n private row(label: string): HTMLDivElement {\r\n const row = document.createElement('div');\r\n row.className = 'tcw-tree-row';\r\n const name = document.createElement('span');\r\n name.className = 'tcw-tree-name';\r\n name.textContent = label;\r\n name.title = label;\r\n row.appendChild(name);\r\n return row;\r\n }\r\n\r\n private emptyRow(text: string): HTMLDivElement {\r\n const el = document.createElement('div');\r\n el.className = 'tcw-tree-empty';\r\n el.textContent = text;\r\n return el;\r\n }\r\n\r\n private iconButton(icon: string, label: string, extraClass: string, onClick: () => void): HTMLButtonElement {\r\n const btn = document.createElement('button');\r\n btn.type = 'button';\r\n btn.className = `tcw-tree-btn ${extraClass}`.trim();\r\n btn.setAttribute('aria-label', label);\r\n btn.title = label;\r\n btn.innerHTML = createIcon(icon, 14);\r\n btn.addEventListener('click', onClick);\r\n return btn;\r\n }\r\n}\r\n\r\nconst DRAWING_TYPE_LABELS: Record<string, string> = {\r\n trendLine: 'Trend Line',\r\n ray: 'Ray',\r\n extendedLine: 'Extended Line',\r\n horizontalLine: 'Horizontal Line',\r\n horizontalRay: 'Horizontal Ray',\r\n crossLine: 'Cross Line',\r\n infoLine: 'Info Line',\r\n trendAngle: 'Trend Angle',\r\n circle: 'Circle',\r\n fibChannel: 'Fib Channel',\r\n fibSpeedResistanceFan: 'Fib Speed Resistance Fan',\r\n schiffPitchfork: 'Schiff Pitchfork',\r\n modifiedSchiffPitchfork: 'Modified Schiff Pitchfork',\r\n xabcdPattern: 'XABCD Pattern',\r\n abcdPattern: 'ABCD Pattern',\r\n headAndShoulders: 'Head and Shoulders',\r\n dateAndPriceRange: 'Date and Price Range',\r\n cyclicLines: 'Cyclic Lines',\r\n priceLabel: 'Price Label',\r\n verticalLine: 'Vertical Line',\r\n rectangle: 'Rectangle',\r\n ellipse: 'Ellipse',\r\n triangle: 'Triangle',\r\n arrow: 'Arrow',\r\n parallelChannel: 'Parallel Channel',\r\n regressionChannel: 'Regression Channel',\r\n pitchfork: 'Pitchfork',\r\n fibRetracement: 'Fib Retracement',\r\n fibExtension: 'Fib Extension',\r\n fibTimeZones: 'Fib Time Zones',\r\n gannBox: 'Gann Box',\r\n gannFan: 'Gann Fan',\r\n elliottWave: 'Elliott Wave',\r\n priceRange: 'Price Range',\r\n dateRange: 'Date Range',\r\n measure: 'Measure',\r\n text: 'Text',\r\n textAnnotation: 'Text',\r\n anchoredVWAP: 'Anchored VWAP',\r\n volumeProfileRange: 'Volume Profile',\r\n riskReward: 'Long/Short Position',\r\n};\r\n\r\n/** Human-readable label for a drawing type, falling back to the raw key. */\r\nexport function drawingTypeLabel(type: string): string {\r\n return DRAWING_TYPE_LABELS[type] ?? type;\r\n}\r\n","import { createIcon } from './icons.js';\r\n\r\nexport type IndicatorParamValue = number | string | boolean;\r\n\r\nexport interface IndicatorSettingsTarget {\r\n instanceId: string;\r\n name: string;\r\n /** Default config — defines the editable keys and their types. */\r\n defaults: Record<string, unknown>;\r\n /** Current values, overlaid on defaults. */\r\n params: Record<string, unknown>;\r\n}\r\n\r\nexport interface IndicatorSettingsCallbacks {\r\n onApply: (instanceId: string, params: Record<string, IndicatorParamValue>) => void;\r\n onClose: () => void;\r\n}\r\n\r\nconst HEX_RE = /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;\r\n\r\nfunction titleCase(key: string): string {\r\n // camelCase / snake_case → \"Title Case\"\r\n return key\r\n .replace(/_/g, ' ')\r\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\r\n .replace(/^./, (c) => c.toUpperCase());\r\n}\r\n\r\n/**\r\n * Per-indicator parameter editor. Introspects the indicator's default config to\r\n * decide each control (number → stepper, boolean → toggle, hex string → color,\r\n * other string → text) and applies edits live via `onApply`.\r\n */\r\nexport class WidgetIndicatorSettings {\r\n private backdrop: HTMLDivElement;\r\n private modal: HTMLDivElement;\r\n private bodyEl: HTMLDivElement;\r\n private titleEl: HTMLHeadingElement;\r\n private callbacks: IndicatorSettingsCallbacks;\r\n private target: IndicatorSettingsTarget | null = null;\r\n private draft: Record<string, IndicatorParamValue> = {};\r\n\r\n constructor(host: HTMLElement, callbacks: IndicatorSettingsCallbacks) {\r\n this.callbacks = callbacks;\r\n\r\n this.backdrop = document.createElement('div');\r\n this.backdrop.className = 'tcw-modal-backdrop';\r\n this.backdrop.hidden = true;\r\n this.backdrop.addEventListener('click', (e) => {\r\n if (e.target === this.backdrop) this.close();\r\n });\r\n\r\n this.modal = document.createElement('div');\r\n this.modal.className = 'tcw-modal tcw-modal-narrow';\r\n\r\n const header = document.createElement('div');\r\n header.className = 'tcw-modal-header';\r\n this.titleEl = document.createElement('h3');\r\n this.titleEl.textContent = 'Indicator';\r\n const closeBtn = document.createElement('button');\r\n closeBtn.className = 'tcw-modal-close';\r\n closeBtn.setAttribute('aria-label', 'Close');\r\n closeBtn.innerHTML = createIcon('x', 16);\r\n closeBtn.addEventListener('click', () => this.close());\r\n header.appendChild(this.titleEl);\r\n header.appendChild(closeBtn);\r\n\r\n this.bodyEl = document.createElement('div');\r\n this.bodyEl.className = 'tcw-modal-body';\r\n\r\n const footer = document.createElement('div');\r\n footer.className = 'tcw-modal-footer';\r\n const resetBtn = document.createElement('button');\r\n resetBtn.className = 'tcw-reset-link';\r\n resetBtn.textContent = 'Reset to defaults';\r\n resetBtn.addEventListener('click', () => this.resetDefaults());\r\n const doneBtn = document.createElement('button');\r\n doneBtn.className = 'tcw-done-btn';\r\n doneBtn.textContent = 'Done';\r\n doneBtn.addEventListener('click', () => this.close());\r\n footer.appendChild(resetBtn);\r\n footer.appendChild(doneBtn);\r\n\r\n this.modal.appendChild(header);\r\n this.modal.appendChild(this.bodyEl);\r\n this.modal.appendChild(footer);\r\n this.backdrop.appendChild(this.modal);\r\n host.appendChild(this.backdrop);\r\n }\r\n\r\n open(target: IndicatorSettingsTarget): void {\r\n this.target = target;\r\n this.titleEl.textContent = `${target.name} settings`;\r\n this.draft = {};\r\n this.renderFields();\r\n this.backdrop.hidden = false;\r\n }\r\n\r\n close(): void {\r\n this.backdrop.hidden = true;\r\n this.target = null;\r\n this.callbacks.onClose();\r\n }\r\n\r\n isOpen(): boolean {\r\n return !this.backdrop.hidden;\r\n }\r\n\r\n destroy(): void {\r\n this.backdrop.remove();\r\n }\r\n\r\n private currentValue(key: string): IndicatorParamValue {\r\n if (key in this.draft) return this.draft[key];\r\n const cur = this.target?.params[key];\r\n const def = this.target?.defaults[key];\r\n const val = cur ?? def;\r\n return val as IndicatorParamValue;\r\n }\r\n\r\n private setValue(key: string, value: IndicatorParamValue): void {\r\n if (!this.target) return;\r\n this.draft[key] = value;\r\n this.callbacks.onApply(this.target.instanceId, { ...this.draft });\r\n }\r\n\r\n private resetDefaults(): void {\r\n if (!this.target) return;\r\n const reset: Record<string, IndicatorParamValue> = {};\r\n for (const [key, def] of Object.entries(this.target.defaults)) {\r\n reset[key] = def as IndicatorParamValue;\r\n }\r\n this.draft = reset;\r\n this.callbacks.onApply(this.target.instanceId, { ...reset });\r\n this.renderFields();\r\n }\r\n\r\n private renderFields(): void {\r\n this.bodyEl.replaceChildren();\r\n if (!this.target) return;\r\n\r\n const section = document.createElement('div');\r\n section.className = 'tcw-settings-section';\r\n\r\n const keys = Object.keys(this.target.defaults);\r\n if (keys.length === 0) {\r\n const empty = document.createElement('div');\r\n empty.className = 'tcw-settings-label';\r\n empty.textContent = 'This indicator has no adjustable parameters.';\r\n section.appendChild(empty);\r\n }\r\n\r\n for (const key of keys) {\r\n section.appendChild(this.fieldRow(key));\r\n }\r\n this.bodyEl.appendChild(section);\r\n }\r\n\r\n private fieldRow(key: string): HTMLDivElement {\r\n const row = document.createElement('div');\r\n row.className = 'tcw-settings-row';\r\n const label = document.createElement('span');\r\n label.className = 'tcw-settings-label';\r\n label.textContent = titleCase(key);\r\n row.appendChild(label);\r\n\r\n const value = this.currentValue(key);\r\n const defType = typeof (this.target?.defaults[key] ?? value);\r\n\r\n if (defType === 'boolean') {\r\n row.appendChild(this.toggleControl(key, Boolean(value)));\r\n } else if (defType === 'number') {\r\n row.appendChild(this.numberControl(key, Number(value)));\r\n } else if (typeof value === 'string' && HEX_RE.test(value)) {\r\n row.appendChild(this.colorControl(key, value));\r\n } else {\r\n row.appendChild(this.textControl(key, String(value ?? '')));\r\n }\r\n return row;\r\n }\r\n\r\n private toggleControl(key: string, value: boolean): HTMLButtonElement {\r\n const toggle = document.createElement('button');\r\n toggle.className = `tcw-toggle${value ? ' tcw-on' : ''}`;\r\n toggle.type = 'button';\r\n toggle.addEventListener('click', () => {\r\n const next = !toggle.classList.contains('tcw-on');\r\n toggle.classList.toggle('tcw-on', next);\r\n this.setValue(key, next);\r\n });\r\n return toggle;\r\n }\r\n\r\n private numberControl(key: string, value: number): HTMLInputElement {\r\n const input = document.createElement('input');\r\n input.type = 'number';\r\n input.className = 'tcw-indi-input';\r\n input.value = String(value);\r\n // Integer-looking defaults step by 1; fractional defaults step by 0.1.\r\n input.step = Number.isInteger(value) ? '1' : '0.1';\r\n input.addEventListener('change', () => {\r\n const n = Number(input.value);\r\n if (Number.isFinite(n)) this.setValue(key, n);\r\n });\r\n return input;\r\n }\r\n\r\n private colorControl(key: string, value: string): HTMLInputElement {\r\n const input = document.createElement('input');\r\n input.type = 'color';\r\n input.className = 'tcw-indi-color';\r\n input.value = value.length === 4 ? expandHex(value) : value;\r\n input.addEventListener('input', () => this.setValue(key, input.value));\r\n return input;\r\n }\r\n\r\n private textControl(key: string, value: string): HTMLInputElement {\r\n const input = document.createElement('input');\r\n input.type = 'text';\r\n input.className = 'tcw-indi-input';\r\n input.value = value;\r\n input.addEventListener('change', () => this.setValue(key, input.value));\r\n return input;\r\n }\r\n}\r\n\r\nfunction expandHex(short: string): string {\r\n // #abc → #aabbcc\r\n const r = short[1], g = short[2], b = short[3];\r\n return `#${r}${r}${g}${g}${b}${b}`;\r\n}\r\n","import type { DrawingStyle } from '@tradecanvas/commons';\r\n\r\nexport interface DrawingStyleTemplate {\r\n name: string;\r\n style: Partial<DrawingStyle>;\r\n}\r\n\r\n/** Minimal storage surface — satisfied by `localStorage` and easy to mock. */\r\nexport interface KeyValueStorage {\r\n getItem(key: string): string | null;\r\n setItem(key: string, value: string): void;\r\n}\r\n\r\nfunction defaultStorage(): KeyValueStorage | null {\r\n try {\r\n return typeof localStorage !== 'undefined' ? localStorage : null;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nconst STYLE_KEYS: (keyof DrawingStyle)[] = [\r\n 'color', 'lineWidth', 'lineStyle', 'fillColor', 'fillOpacity', 'fontSize',\r\n];\r\n\r\n/** Keep only known style keys — guards against junk persisted by older builds. */\r\nfunction sanitizeStyle(raw: unknown): Partial<DrawingStyle> {\r\n if (!raw || typeof raw !== 'object') return {};\r\n const out: Partial<DrawingStyle> = {};\r\n const obj = raw as Record<string, unknown>;\r\n for (const key of STYLE_KEYS) {\r\n if (obj[key] !== undefined) (out as Record<string, unknown>)[key] = obj[key];\r\n }\r\n return out;\r\n}\r\n\r\n/**\r\n * Named drawing-style presets, persisted to a key-value store. Templates are\r\n * upserted by name (case-sensitive) and ordered most-recently-saved last.\r\n */\r\nexport class DrawingTemplateStore {\r\n private templates: DrawingStyleTemplate[] = [];\r\n\r\n constructor(\r\n private storageKey = 'tcw:draw-templates',\r\n private storage: KeyValueStorage | null = defaultStorage(),\r\n ) {\r\n this.load();\r\n }\r\n\r\n list(): DrawingStyleTemplate[] {\r\n return this.templates.map((t) => ({ name: t.name, style: { ...t.style } }));\r\n }\r\n\r\n get(name: string): DrawingStyleTemplate | null {\r\n const t = this.templates.find((x) => x.name === name);\r\n return t ? { name: t.name, style: { ...t.style } } : null;\r\n }\r\n\r\n /** Insert or replace a template by name. */\r\n save(name: string, style: Partial<DrawingStyle>): void {\r\n const trimmed = name.trim();\r\n if (!trimmed) return;\r\n const clean = sanitizeStyle(style);\r\n this.templates = this.templates.filter((t) => t.name !== trimmed);\r\n this.templates.push({ name: trimmed, style: clean });\r\n this.persist();\r\n }\r\n\r\n remove(name: string): void {\r\n const next = this.templates.filter((t) => t.name !== name);\r\n if (next.length === this.templates.length) return;\r\n this.templates = next;\r\n this.persist();\r\n }\r\n\r\n clear(): void {\r\n this.templates = [];\r\n this.persist();\r\n }\r\n\r\n private load(): void {\r\n if (!this.storage) return;\r\n try {\r\n const raw = this.storage.getItem(this.storageKey);\r\n if (!raw) return;\r\n const parsed = JSON.parse(raw);\r\n if (!Array.isArray(parsed)) return;\r\n this.templates = parsed\r\n .filter((t) => t && typeof t.name === 'string')\r\n .map((t) => ({ name: t.name, style: sanitizeStyle(t.style) }));\r\n } catch {\r\n // Corrupt or unavailable storage — start empty.\r\n }\r\n }\r\n\r\n private persist(): void {\r\n if (!this.storage) return;\r\n try {\r\n this.storage.setItem(this.storageKey, JSON.stringify(this.templates));\r\n } catch {\r\n // Storage full or blocked — keep the in-memory copy.\r\n }\r\n }\r\n}\r\n","import type { DrawingStyle } from '@tradecanvas/commons';\r\nimport { createIcon } from './icons.js';\r\nimport { DrawingTemplateStore } from './DrawingTemplateStore.js';\r\n\r\nexport interface DrawingStyleCallbacks {\r\n /** Apply a style change to the active (next) drawing and the selected one. */\r\n onStyleChange: (style: Partial<DrawingStyle>) => void;\r\n /** Current active drawing style, for seeding controls and saving templates. */\r\n getStyle: () => DrawingStyle;\r\n}\r\n\r\nconst SWATCHES = ['#2962ff', '#089981', '#f23645', '#ff9800', '#ab47bc', '#26c6da', '#ffffff', '#787b86'];\r\nconst WIDTHS = [1, 2, 3, 4];\r\nconst LINE_STYLES: DrawingStyle['lineStyle'][] = ['solid', 'dashed', 'dotted'];\r\n\r\n/**\r\n * Drawing style popover — pick colour, line width, and line style for the next\r\n * drawing (and the selected one), plus save/apply named style templates\r\n * persisted via `DrawingTemplateStore`.\r\n */\r\nexport class WidgetDrawingStyle {\r\n private el: HTMLDivElement;\r\n private templatesEl: HTMLDivElement;\r\n private nameInput: HTMLInputElement;\r\n private callbacks: DrawingStyleCallbacks;\r\n private store: DrawingTemplateStore;\r\n private open = false;\r\n\r\n constructor(host: HTMLElement, callbacks: DrawingStyleCallbacks, store: DrawingTemplateStore) {\r\n this.callbacks = callbacks;\r\n this.store = store;\r\n\r\n this.el = document.createElement('div');\r\n this.el.className = 'tcw-style-panel';\r\n this.el.hidden = true;\r\n\r\n const header = document.createElement('div');\r\n header.className = 'tcw-style-header';\r\n const title = document.createElement('span');\r\n title.textContent = 'Drawing Style';\r\n const closeBtn = document.createElement('button');\r\n closeBtn.type = 'button';\r\n closeBtn.className = 'tcw-style-close';\r\n closeBtn.setAttribute('aria-label', 'Close');\r\n closeBtn.innerHTML = createIcon('x', 14);\r\n closeBtn.addEventListener('click', () => this.close());\r\n header.appendChild(title);\r\n header.appendChild(closeBtn);\r\n this.el.appendChild(header);\r\n\r\n this.el.appendChild(this.colorRow());\r\n this.el.appendChild(this.widthRow());\r\n this.el.appendChild(this.lineStyleRow());\r\n\r\n // Templates\r\n const tmplHead = document.createElement('div');\r\n tmplHead.className = 'tcw-style-subhead';\r\n tmplHead.textContent = 'Templates';\r\n this.el.appendChild(tmplHead);\r\n\r\n const saveRow = document.createElement('div');\r\n saveRow.className = 'tcw-style-save';\r\n this.nameInput = document.createElement('input');\r\n this.nameInput.type = 'text';\r\n this.nameInput.placeholder = 'Template name';\r\n this.nameInput.className = 'tcw-style-name';\r\n const saveBtn = document.createElement('button');\r\n saveBtn.type = 'button';\r\n saveBtn.className = 'tcw-style-savebtn';\r\n saveBtn.innerHTML = `${createIcon('plus', 13)}<span>Save</span>`;\r\n saveBtn.addEventListener('click', () => this.saveTemplate());\r\n saveRow.appendChild(this.nameInput);\r\n saveRow.appendChild(saveBtn);\r\n this.el.appendChild(saveRow);\r\n\r\n this.templatesEl = document.createElement('div');\r\n this.templatesEl.className = 'tcw-style-templates';\r\n this.el.appendChild(this.templatesEl);\r\n\r\n host.appendChild(this.el);\r\n this.renderTemplates();\r\n }\r\n\r\n isOpen(): boolean {\r\n return this.open;\r\n }\r\n\r\n toggle(): void {\r\n this.open ? this.close() : this.openPanel();\r\n }\r\n\r\n openPanel(): void {\r\n this.open = true;\r\n this.el.hidden = false;\r\n this.syncActiveControls();\r\n this.renderTemplates();\r\n }\r\n\r\n close(): void {\r\n this.open = false;\r\n this.el.hidden = true;\r\n }\r\n\r\n destroy(): void {\r\n this.el.remove();\r\n }\r\n\r\n private colorRow(): HTMLDivElement {\r\n const row = document.createElement('div');\r\n row.className = 'tcw-style-row tcw-style-colors';\r\n for (const c of SWATCHES) {\r\n const sw = document.createElement('button');\r\n sw.type = 'button';\r\n sw.className = 'tcw-style-swatch';\r\n sw.style.background = c;\r\n sw.dataset.color = c;\r\n sw.setAttribute('aria-label', c);\r\n sw.addEventListener('click', () => this.applyStyle({ color: c }));\r\n row.appendChild(sw);\r\n }\r\n const picker = document.createElement('input');\r\n picker.type = 'color';\r\n picker.className = 'tcw-style-picker';\r\n picker.addEventListener('input', () => this.applyStyle({ color: picker.value }));\r\n row.appendChild(picker);\r\n return row;\r\n }\r\n\r\n private widthRow(): HTMLDivElement {\r\n const row = document.createElement('div');\r\n row.className = 'tcw-style-row tcw-style-widths';\r\n for (const w of WIDTHS) {\r\n const btn = document.createElement('button');\r\n btn.type = 'button';\r\n btn.className = 'tcw-style-width';\r\n btn.dataset.width = String(w);\r\n const bar = document.createElement('span');\r\n bar.style.height = `${w}px`;\r\n btn.appendChild(bar);\r\n btn.addEventListener('click', () => this.applyStyle({ lineWidth: w }));\r\n row.appendChild(btn);\r\n }\r\n return row;\r\n }\r\n\r\n private lineStyleRow(): HTMLDivElement {\r\n const row = document.createElement('div');\r\n row.className = 'tcw-style-row tcw-style-dashes';\r\n for (const ls of LINE_STYLES) {\r\n const btn = document.createElement('button');\r\n btn.type = 'button';\r\n btn.className = 'tcw-style-dash';\r\n btn.dataset.linestyle = ls;\r\n btn.textContent = ls === 'solid' ? '──' : ls === 'dashed' ? '╌╌' : '┄┄';\r\n btn.title = ls;\r\n btn.addEventListener('click', () => this.applyStyle({ lineStyle: ls }));\r\n row.appendChild(btn);\r\n }\r\n return row;\r\n }\r\n\r\n private applyStyle(patch: Partial<DrawingStyle>): void {\r\n this.callbacks.onStyleChange(patch);\r\n this.syncActiveControls();\r\n }\r\n\r\n /** Mark the controls matching the current active style. */\r\n private syncActiveControls(): void {\r\n const style = this.callbacks.getStyle();\r\n this.el.querySelectorAll<HTMLElement>('.tcw-style-swatch').forEach((sw) => {\r\n sw.classList.toggle('tcw-on', sw.dataset.color?.toLowerCase() === style.color?.toLowerCase());\r\n });\r\n this.el.querySelectorAll<HTMLElement>('.tcw-style-width').forEach((b) => {\r\n b.classList.toggle('tcw-on', Number(b.dataset.width) === style.lineWidth);\r\n });\r\n this.el.querySelectorAll<HTMLElement>('.tcw-style-dash').forEach((b) => {\r\n b.classList.toggle('tcw-on', b.dataset.linestyle === style.lineStyle);\r\n });\r\n }\r\n\r\n private saveTemplate(): void {\r\n const name = this.nameInput.value.trim();\r\n if (!name) return;\r\n this.store.save(name, this.callbacks.getStyle());\r\n this.nameInput.value = '';\r\n this.renderTemplates();\r\n }\r\n\r\n private renderTemplates(): void {\r\n this.templatesEl.replaceChildren();\r\n const templates = this.store.list();\r\n if (templates.length === 0) {\r\n const empty = document.createElement('div');\r\n empty.className = 'tcw-style-empty';\r\n empty.textContent = 'No saved templates';\r\n this.templatesEl.appendChild(empty);\r\n return;\r\n }\r\n for (const t of templates) {\r\n const row = document.createElement('div');\r\n row.className = 'tcw-style-template';\r\n\r\n const apply = document.createElement('button');\r\n apply.type = 'button';\r\n apply.className = 'tcw-style-apply';\r\n const dot = document.createElement('span');\r\n dot.className = 'tcw-style-tdot';\r\n dot.style.background = (t.style.color as string) ?? 'var(--tcw-text-muted)';\r\n const label = document.createElement('span');\r\n label.textContent = t.name;\r\n apply.appendChild(dot);\r\n apply.appendChild(label);\r\n apply.addEventListener('click', () => {\r\n this.callbacks.onStyleChange({ ...t.style });\r\n this.syncActiveControls();\r\n });\r\n\r\n const del = document.createElement('button');\r\n del.type = 'button';\r\n del.className = 'tcw-style-tdel';\r\n del.setAttribute('aria-label', 'Delete template');\r\n del.innerHTML = createIcon('trash', 13);\r\n del.addEventListener('click', () => {\r\n this.store.remove(t.name);\r\n this.renderTemplates();\r\n });\r\n\r\n row.appendChild(apply);\r\n row.appendChild(del);\r\n this.templatesEl.appendChild(row);\r\n }\r\n }\r\n}\r\n","import type { KeyValueStorage } from './DrawingTemplateStore.js';\r\n\r\nfunction defaultStorage(): KeyValueStorage | null {\r\n try {\r\n return typeof localStorage !== 'undefined' ? localStorage : null;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * An ordered, de-duplicated set of pinned drawing-tool ids, persisted to a\r\n * key-value store. Order is insertion order (most-recently-pinned last).\r\n */\r\nexport class DrawingFavoritesStore {\r\n private favorites: string[] = [];\r\n\r\n constructor(\r\n private storageKey = 'tcw:draw-favorites',\r\n private storage: KeyValueStorage | null = defaultStorage(),\r\n ) {\r\n this.load();\r\n }\r\n\r\n list(): string[] {\r\n return [...this.favorites];\r\n }\r\n\r\n has(tool: string): boolean {\r\n return this.favorites.includes(tool);\r\n }\r\n\r\n add(tool: string): void {\r\n if (!tool || this.favorites.includes(tool)) return;\r\n this.favorites = [...this.favorites, tool];\r\n this.persist();\r\n }\r\n\r\n remove(tool: string): void {\r\n if (!this.favorites.includes(tool)) return;\r\n this.favorites = this.favorites.filter((t) => t !== tool);\r\n this.persist();\r\n }\r\n\r\n /** Toggle a tool's pinned state. Returns the new state (true = pinned). */\r\n toggle(tool: string): boolean {\r\n if (this.has(tool)) {\r\n this.remove(tool);\r\n return false;\r\n }\r\n this.add(tool);\r\n return true;\r\n }\r\n\r\n /** Seed the favorites only when none are stored yet (first run). */\r\n seedDefaults(tools: string[]): void {\r\n if (this.favorites.length > 0) return;\r\n this.favorites = [...new Set(tools.filter(Boolean))];\r\n this.persist();\r\n }\r\n\r\n private load(): void {\r\n if (!this.storage) return;\r\n try {\r\n const raw = this.storage.getItem(this.storageKey);\r\n if (!raw) return;\r\n const parsed = JSON.parse(raw);\r\n if (Array.isArray(parsed)) {\r\n this.favorites = [...new Set(parsed.filter((t) => typeof t === 'string'))];\r\n }\r\n } catch {\r\n // Corrupt or unavailable — start empty.\r\n }\r\n }\r\n\r\n private persist(): void {\r\n if (!this.storage) return;\r\n try {\r\n this.storage.setItem(this.storageKey, JSON.stringify(this.favorites));\r\n } catch {\r\n // Storage full or blocked — keep the in-memory copy.\r\n }\r\n }\r\n}\r\n","import { createIcon } from './icons.js';\r\n\r\nexport interface BracketBarCallbacks {\r\n onConfirm: () => void;\r\n onCancel: () => void;\r\n}\r\n\r\n/**\r\n * Floating confirm/cancel bar shown while a bracket order is being placed.\r\n * The live entry / SL / TP numbers are drawn on the chart canvas; this bar\r\n * just carries the commit and discard actions (also bound to Enter / Esc).\r\n */\r\nexport class WidgetBracketBar {\r\n private el: HTMLDivElement;\r\n private labelEl: HTMLSpanElement;\r\n private callbacks: BracketBarCallbacks;\r\n private visible = false;\r\n\r\n constructor(host: HTMLElement, callbacks: BracketBarCallbacks) {\r\n this.callbacks = callbacks;\r\n\r\n this.el = document.createElement('div');\r\n this.el.className = 'tcw-bracket-bar';\r\n this.el.hidden = true;\r\n\r\n this.labelEl = document.createElement('span');\r\n this.labelEl.className = 'tcw-bracket-label';\r\n this.el.appendChild(this.labelEl);\r\n\r\n const hint = document.createElement('span');\r\n hint.className = 'tcw-bracket-hint';\r\n hint.textContent = 'drag lines to adjust';\r\n this.el.appendChild(hint);\r\n\r\n const cancel = document.createElement('button');\r\n cancel.type = 'button';\r\n cancel.className = 'tcw-bracket-cancel';\r\n cancel.innerHTML = `${createIcon('x', 14)}<span>Cancel</span>`;\r\n cancel.addEventListener('click', () => this.callbacks.onCancel());\r\n\r\n const confirm = document.createElement('button');\r\n confirm.type = 'button';\r\n confirm.className = 'tcw-bracket-confirm';\r\n confirm.innerHTML = `${createIcon('check', 14)}<span>Place</span>`;\r\n confirm.addEventListener('click', () => this.callbacks.onConfirm());\r\n\r\n this.el.appendChild(cancel);\r\n this.el.appendChild(confirm);\r\n host.appendChild(this.el);\r\n }\r\n\r\n show(side: 'buy' | 'sell'): void {\r\n this.visible = true;\r\n this.labelEl.textContent = side === 'buy' ? 'Long bracket' : 'Short bracket';\r\n this.labelEl.dataset.side = side;\r\n this.el.hidden = false;\r\n }\r\n\r\n hide(): void {\r\n this.visible = false;\r\n this.el.hidden = true;\r\n }\r\n\r\n isVisible(): boolean {\r\n return this.visible;\r\n }\r\n\r\n destroy(): void {\r\n this.el.remove();\r\n }\r\n}\r\n","export interface AlertNotifyOptions {\r\n /** Play a sound on trigger. `true` = built-in beep, string = audio URL. Default `false`. */\r\n sound?: boolean | string;\r\n /** Show a desktop notification (requests permission on first use). Default `false`. */\r\n desktop?: boolean;\r\n /** Title for desktop notifications. Default `'Price alert'`. */\r\n title?: string;\r\n}\r\n\r\n/** True when the Notification API is present and not denied. */\r\nexport function canRequestNotifications(): boolean {\r\n return typeof Notification !== 'undefined' && Notification.permission !== 'denied';\r\n}\r\n\r\n/**\r\n * Plays a sound and/or raises a desktop notification when a price alert fires.\r\n * Browser-API heavy by nature — every entry point is guarded so it degrades to\r\n * a no-op in SSR, unsupported browsers, or when permission is denied.\r\n */\r\nexport class AlertNotifier {\r\n private options: AlertNotifyOptions;\r\n private audioCtx: AudioContext | null = null;\r\n private audioEl: HTMLAudioElement | null = null;\r\n private permissionAsked = false;\r\n\r\n constructor(options: AlertNotifyOptions = {}) {\r\n this.options = options;\r\n if (typeof options.sound === 'string') {\r\n try {\r\n this.audioEl = new Audio(options.sound);\r\n this.audioEl.preload = 'auto';\r\n } catch {\r\n this.audioEl = null;\r\n }\r\n }\r\n // Request notification permission up front so the first alert isn't silent.\r\n if (options.desktop) this.ensurePermission();\r\n }\r\n\r\n setOptions(options: AlertNotifyOptions): void {\r\n this.options = { ...this.options, ...options };\r\n }\r\n\r\n /** Fire the configured notifications for a triggered alert. */\r\n notify(message: string): void {\r\n if (this.options.sound) this.playSound();\r\n if (this.options.desktop) this.showDesktop(message);\r\n }\r\n\r\n private playSound(): void {\r\n if (this.audioEl) {\r\n this.audioEl.currentTime = 0;\r\n void this.audioEl.play().catch(() => {});\r\n return;\r\n }\r\n this.beep();\r\n }\r\n\r\n /** A short two-tone beep via Web Audio — no asset required. */\r\n private beep(): void {\r\n try {\r\n const Ctx = window.AudioContext ?? (window as unknown as { webkitAudioContext?: typeof AudioContext }).webkitAudioContext;\r\n if (!Ctx) return;\r\n if (!this.audioCtx) this.audioCtx = new Ctx();\r\n const ctx = this.audioCtx;\r\n const now = ctx.currentTime;\r\n const gain = ctx.createGain();\r\n gain.gain.setValueAtTime(0.0001, now);\r\n gain.gain.exponentialRampToValueAtTime(0.2, now + 0.01);\r\n gain.gain.exponentialRampToValueAtTime(0.0001, now + 0.35);\r\n gain.connect(ctx.destination);\r\n const osc = ctx.createOscillator();\r\n osc.type = 'sine';\r\n osc.frequency.setValueAtTime(880, now);\r\n osc.frequency.setValueAtTime(1320, now + 0.16);\r\n osc.connect(gain);\r\n osc.start(now);\r\n osc.stop(now + 0.36);\r\n } catch {\r\n // Audio unavailable or blocked by autoplay policy — silent.\r\n }\r\n }\r\n\r\n private ensurePermission(): void {\r\n if (this.permissionAsked) return;\r\n this.permissionAsked = true;\r\n if (typeof Notification === 'undefined') return;\r\n if (Notification.permission === 'default') {\r\n void Notification.requestPermission().catch(() => {});\r\n }\r\n }\r\n\r\n private showDesktop(message: string): void {\r\n if (typeof Notification === 'undefined') return;\r\n if (Notification.permission !== 'granted') {\r\n this.ensurePermission();\r\n return;\r\n }\r\n try {\r\n new Notification(this.options.title ?? 'Price alert', { body: message });\r\n } catch {\r\n // Some browsers throw if not invoked from a user gesture — ignore.\r\n }\r\n }\r\n\r\n destroy(): void {\r\n try {\r\n void this.audioCtx?.close();\r\n } catch {\r\n // ignore\r\n }\r\n this.audioCtx = null;\r\n this.audioEl = null;\r\n }\r\n}\r\n","import type { DepthData } from '@tradecanvas/commons';\r\n\r\nexport interface LadderRow {\r\n price: number;\r\n bidVolume: number;\r\n askVolume: number;\r\n}\r\n\r\nexport interface LadderModel {\r\n /** Rows ordered high → low price (asks on top, bids below). */\r\n rows: LadderRow[];\r\n /** Largest single-side volume across the shown rows (for bar scaling). */\r\n maxVolume: number;\r\n /** Midpoint between best bid and best ask, or null if a side is empty. */\r\n mid: number | null;\r\n}\r\n\r\n/**\r\n * Build a depth-of-market ladder from an order book: the best `maxLevels` asks\r\n * (lowest prices) and best `maxLevels` bids (highest prices), merged into rows\r\n * ordered high→low. A price present on both sides is merged into one row.\r\n */\r\nexport function buildLadderRows(data: DepthData, maxLevels = 12): LadderModel {\r\n const asks = [...data.asks].sort((a, b) => a.price - b.price).slice(0, maxLevels);\r\n const bids = [...data.bids].sort((a, b) => b.price - a.price).slice(0, maxLevels);\r\n\r\n const bestAsk = asks.length > 0 ? asks[0].price : null;\r\n const bestBid = bids.length > 0 ? bids[0].price : null;\r\n const mid = bestAsk !== null && bestBid !== null ? (bestAsk + bestBid) / 2 : null;\r\n\r\n const byPrice = new Map<number, LadderRow>();\r\n const rowAt = (price: number): LadderRow => {\r\n let row = byPrice.get(price);\r\n if (!row) {\r\n row = { price, bidVolume: 0, askVolume: 0 };\r\n byPrice.set(price, row);\r\n }\r\n return row;\r\n };\r\n for (const a of asks) rowAt(a.price).askVolume += a.volume;\r\n for (const b of bids) rowAt(b.price).bidVolume += b.volume;\r\n\r\n const rows = [...byPrice.values()].sort((a, b) => b.price - a.price);\r\n let maxVolume = 0;\r\n for (const r of rows) maxVolume = Math.max(maxVolume, r.bidVolume, r.askVolume);\r\n\r\n return { rows, maxVolume, mid };\r\n}\r\n","import type { DepthData } from '@tradecanvas/commons';\r\nimport { createIcon } from './icons.js';\r\nimport { buildLadderRows, type LadderModel } from './ladderRows.js';\r\n\r\nexport interface DepthLadderCallbacks {\r\n /** Buy at `price` (clicked an ask cell) or sell at `price` (clicked a bid cell). */\r\n onTrade: (side: 'buy' | 'sell', price: number) => void;\r\n formatPrice: (price: number) => string;\r\n}\r\n\r\n/**\r\n * Depth-of-market ladder (DOM). Renders the order book as price rows with bid\r\n * and ask size columns; clicking an ask cell buys at that price, a bid cell\r\n * sells. Fed by `setData(depth)`; the bar widths scale to the largest visible\r\n * size.\r\n */\r\nexport class WidgetDepthLadder {\r\n private el: HTMLDivElement;\r\n private bodyEl: HTMLDivElement;\r\n private callbacks: DepthLadderCallbacks;\r\n private open = false;\r\n private levels: number;\r\n\r\n constructor(host: HTMLElement, callbacks: DepthLadderCallbacks, levels = 12) {\r\n this.callbacks = callbacks;\r\n this.levels = levels;\r\n\r\n this.el = document.createElement('div');\r\n this.el.className = 'tcw-ladder';\r\n this.el.hidden = true;\r\n\r\n const header = document.createElement('div');\r\n header.className = 'tcw-ladder-header';\r\n const title = document.createElement('span');\r\n title.textContent = 'Depth Ladder';\r\n const closeBtn = document.createElement('button');\r\n closeBtn.type = 'button';\r\n closeBtn.className = 'tcw-ladder-close';\r\n closeBtn.setAttribute('aria-label', 'Close');\r\n closeBtn.innerHTML = createIcon('x', 14);\r\n closeBtn.addEventListener('click', () => this.close());\r\n header.appendChild(title);\r\n header.appendChild(closeBtn);\r\n this.el.appendChild(header);\r\n\r\n const cols = document.createElement('div');\r\n cols.className = 'tcw-ladder-cols';\r\n cols.innerHTML = '<span>Bid</span><span>Price</span><span>Ask</span>';\r\n this.el.appendChild(cols);\r\n\r\n this.bodyEl = document.createElement('div');\r\n this.bodyEl.className = 'tcw-ladder-body';\r\n this.el.appendChild(this.bodyEl);\r\n\r\n host.appendChild(this.el);\r\n }\r\n\r\n isOpen(): boolean {\r\n return this.open;\r\n }\r\n\r\n toggle(): void {\r\n this.open ? this.close() : this.openPanel();\r\n }\r\n\r\n openPanel(): void {\r\n this.open = true;\r\n this.el.hidden = false;\r\n }\r\n\r\n close(): void {\r\n this.open = false;\r\n this.el.hidden = true;\r\n }\r\n\r\n setData(depth: DepthData | null): void {\r\n if (!depth) {\r\n this.renderEmpty();\r\n return;\r\n }\r\n this.render(buildLadderRows(depth, this.levels));\r\n }\r\n\r\n destroy(): void {\r\n this.el.remove();\r\n }\r\n\r\n private renderEmpty(): void {\r\n this.bodyEl.replaceChildren();\r\n const empty = document.createElement('div');\r\n empty.className = 'tcw-ladder-empty';\r\n empty.textContent = 'No order-book data';\r\n this.bodyEl.appendChild(empty);\r\n }\r\n\r\n private render(model: LadderModel): void {\r\n this.bodyEl.replaceChildren();\r\n if (model.rows.length === 0) {\r\n this.renderEmpty();\r\n return;\r\n }\r\n const inv = model.maxVolume > 0 ? 1 / model.maxVolume : 0;\r\n\r\n for (const row of model.rows) {\r\n const isAsk = row.askVolume > 0;\r\n const tr = document.createElement('div');\r\n tr.className = 'tcw-ladder-row';\r\n\r\n // Bid cell (click → sell at price)\r\n const bid = document.createElement('button');\r\n bid.type = 'button';\r\n bid.className = 'tcw-ladder-cell tcw-ladder-bid';\r\n if (row.bidVolume > 0) {\r\n bid.textContent = formatSize(row.bidVolume);\r\n bid.style.setProperty('--w', `${(row.bidVolume * inv * 100).toFixed(1)}%`);\r\n bid.title = `Sell @ ${this.callbacks.formatPrice(row.price)}`;\r\n bid.addEventListener('click', () => this.callbacks.onTrade('sell', row.price));\r\n } else {\r\n bid.disabled = true;\r\n }\r\n\r\n const price = document.createElement('div');\r\n price.className = `tcw-ladder-price ${isAsk ? 'tcw-ask' : 'tcw-bid'}`;\r\n price.textContent = this.callbacks.formatPrice(row.price);\r\n\r\n // Ask cell (click → buy at price)\r\n const ask = document.createElement('button');\r\n ask.type = 'button';\r\n ask.className = 'tcw-ladder-cell tcw-ladder-ask';\r\n if (row.askVolume > 0) {\r\n ask.textContent = formatSize(row.askVolume);\r\n ask.style.setProperty('--w', `${(row.askVolume * inv * 100).toFixed(1)}%`);\r\n ask.title = `Buy @ ${this.callbacks.formatPrice(row.price)}`;\r\n ask.addEventListener('click', () => this.callbacks.onTrade('buy', row.price));\r\n } else {\r\n ask.disabled = true;\r\n }\r\n\r\n tr.appendChild(bid);\r\n tr.appendChild(price);\r\n tr.appendChild(ask);\r\n this.bodyEl.appendChild(tr);\r\n }\r\n }\r\n}\r\n\r\nfunction formatSize(v: number): string {\r\n if (v >= 1000) return (v / 1000).toFixed(1) + 'k';\r\n if (v >= 1) return v.toFixed(2).replace(/\\.00$/, '');\r\n return v.toPrecision(2);\r\n}\r\n","import { createIcon } from './icons.js';\r\n\r\nexport interface DataWindowIndicator {\r\n name: string;\r\n values: { key: string; value: number }[];\r\n}\r\n\r\nexport interface DataWindowModel {\r\n ohlc: { open: number; high: number; low: number; close: number; volume: number } | null;\r\n change: number;\r\n changePct: number;\r\n indicators: DataWindowIndicator[];\r\n}\r\n\r\nexport interface DataWindowCallbacks {\r\n formatPrice: (price: number) => string;\r\n}\r\n\r\n/**\r\n * Data Window — a floating readout of the exact O/H/L/C/V, change, and every\r\n * active indicator value at the hovered bar. Updated from `crosshairMove`.\r\n */\r\nexport class WidgetDataWindow {\r\n private el: HTMLDivElement;\r\n private bodyEl: HTMLDivElement;\r\n private callbacks: DataWindowCallbacks;\r\n private open = false;\r\n\r\n constructor(host: HTMLElement, callbacks: DataWindowCallbacks) {\r\n this.callbacks = callbacks;\r\n\r\n this.el = document.createElement('div');\r\n this.el.className = 'tcw-datawin';\r\n this.el.hidden = true;\r\n\r\n const header = document.createElement('div');\r\n header.className = 'tcw-datawin-header';\r\n const title = document.createElement('span');\r\n title.textContent = 'Data Window';\r\n const closeBtn = document.createElement('button');\r\n closeBtn.type = 'button';\r\n closeBtn.className = 'tcw-datawin-close';\r\n closeBtn.setAttribute('aria-label', 'Close');\r\n closeBtn.innerHTML = createIcon('x', 14);\r\n closeBtn.addEventListener('click', () => this.close());\r\n header.appendChild(title);\r\n header.appendChild(closeBtn);\r\n this.el.appendChild(header);\r\n\r\n this.bodyEl = document.createElement('div');\r\n this.bodyEl.className = 'tcw-datawin-body';\r\n this.el.appendChild(this.bodyEl);\r\n\r\n host.appendChild(this.el);\r\n }\r\n\r\n isOpen(): boolean {\r\n return this.open;\r\n }\r\n\r\n toggle(): void {\r\n this.open ? this.close() : this.openPanel();\r\n }\r\n\r\n openPanel(): void {\r\n this.open = true;\r\n this.el.hidden = false;\r\n }\r\n\r\n close(): void {\r\n this.open = false;\r\n this.el.hidden = true;\r\n }\r\n\r\n destroy(): void {\r\n this.el.remove();\r\n }\r\n\r\n render(model: DataWindowModel): void {\r\n if (!this.open) return;\r\n this.bodyEl.replaceChildren();\r\n\r\n if (!model.ohlc) {\r\n const empty = document.createElement('div');\r\n empty.className = 'tcw-datawin-empty';\r\n empty.textContent = 'Hover the chart';\r\n this.bodyEl.appendChild(empty);\r\n return;\r\n }\r\n\r\n const fp = this.callbacks.formatPrice;\r\n const o = model.ohlc;\r\n this.bodyEl.appendChild(this.row('Open', fp(o.open)));\r\n this.bodyEl.appendChild(this.row('High', fp(o.high)));\r\n this.bodyEl.appendChild(this.row('Low', fp(o.low)));\r\n this.bodyEl.appendChild(this.row('Close', fp(o.close)));\r\n const tone = model.change > 0 ? 'up' : model.change < 0 ? 'down' : '';\r\n const sign = model.change > 0 ? '+' : '';\r\n this.bodyEl.appendChild(this.row('Change', `${sign}${fp(model.change)} (${sign}${model.changePct.toFixed(2)}%)`, tone));\r\n this.bodyEl.appendChild(this.row('Volume', formatVolume(o.volume)));\r\n\r\n for (const ind of model.indicators) {\r\n const head = document.createElement('div');\r\n head.className = 'tcw-datawin-sub';\r\n head.textContent = ind.name;\r\n this.bodyEl.appendChild(head);\r\n for (const v of ind.values) {\r\n this.bodyEl.appendChild(this.row(v.key, formatNumber(v.value)));\r\n }\r\n }\r\n }\r\n\r\n private row(label: string, value: string, tone = ''): HTMLDivElement {\r\n const row = document.createElement('div');\r\n row.className = 'tcw-datawin-row';\r\n const l = document.createElement('span');\r\n l.className = 'tcw-datawin-label';\r\n l.textContent = label;\r\n const v = document.createElement('span');\r\n v.className = `tcw-datawin-value${tone ? ` tcw-${tone}` : ''}`;\r\n v.textContent = value;\r\n row.appendChild(l);\r\n row.appendChild(v);\r\n return row;\r\n }\r\n}\r\n\r\nfunction formatNumber(v: number): string {\r\n if (!Number.isFinite(v)) return '—';\r\n const abs = Math.abs(v);\r\n if (abs >= 1000) return v.toFixed(2);\r\n if (abs >= 1) return v.toFixed(4);\r\n return v.toPrecision(4);\r\n}\r\n\r\nfunction formatVolume(v: number): string {\r\n if (v >= 1_000_000_000) return (v / 1_000_000_000).toFixed(2) + 'B';\r\n if (v >= 1_000_000) return (v / 1_000_000).toFixed(2) + 'M';\r\n if (v >= 1_000) return (v / 1_000).toFixed(2) + 'K';\r\n return v.toFixed(0);\r\n}\r\n","import type { ChartType, TimeFrame, DrawingState, PriceScaleMode } from '@tradecanvas/commons';\r\n\r\nexport interface ShareableIndicator {\r\n id: string;\r\n params: Record<string, number | string | boolean>;\r\n}\r\n\r\nexport interface ShareableWidgetState {\r\n v: 1;\r\n symbol: string;\r\n timeframe: TimeFrame;\r\n chartType: ChartType;\r\n scaleMode: PriceScaleMode;\r\n indicators: ShareableIndicator[];\r\n drawings: DrawingState[];\r\n}\r\n\r\ninterface NodeBufferCtor {\r\n from(input: string, encoding: string): { toString(encoding: string): string };\r\n}\r\nconst nodeBuffer = (globalThis as { Buffer?: NodeBufferCtor }).Buffer;\r\n\r\nfunction utf8ToBase64(str: string): string {\r\n if (nodeBuffer) return nodeBuffer.from(str, 'utf8').toString('base64');\r\n const bytes = new TextEncoder().encode(str);\r\n let bin = '';\r\n for (const b of bytes) bin += String.fromCharCode(b);\r\n return btoa(bin);\r\n}\r\n\r\nfunction base64ToUtf8(b64: string): string {\r\n if (nodeBuffer) return nodeBuffer.from(b64, 'base64').toString('utf8');\r\n const bin = atob(b64);\r\n const bytes = new Uint8Array(bin.length);\r\n for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i);\r\n return new TextDecoder().decode(bytes);\r\n}\r\n\r\nfunction toBase64Url(b64: string): string {\r\n return b64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\r\n}\r\n\r\nfunction fromBase64Url(s: string): string {\r\n const b64 = s.replace(/-/g, '+').replace(/_/g, '/');\r\n const pad = b64.length % 4 === 0 ? '' : '='.repeat(4 - (b64.length % 4));\r\n return b64 + pad;\r\n}\r\n\r\n/** Encode a shareable widget state to a compact, URL-safe string. */\r\nexport function encodeWidgetState(state: ShareableWidgetState): string {\r\n return toBase64Url(utf8ToBase64(JSON.stringify(state)));\r\n}\r\n\r\n/**\r\n * Decode a shareable-state string. Returns null for anything malformed or of an\r\n * unknown version — callers should treat null as \"ignore and keep current view\".\r\n */\r\nexport function decodeWidgetState(encoded: string): ShareableWidgetState | null {\r\n if (!encoded) return null;\r\n try {\r\n const json = base64ToUtf8(fromBase64Url(encoded));\r\n const obj = JSON.parse(json);\r\n if (!obj || obj.v !== 1 || typeof obj.symbol !== 'string') return null;\r\n return {\r\n v: 1,\r\n symbol: obj.symbol,\r\n timeframe: obj.timeframe,\r\n chartType: obj.chartType,\r\n scaleMode: obj.scaleMode ?? 'regular',\r\n indicators: Array.isArray(obj.indicators) ? obj.indicators : [],\r\n drawings: Array.isArray(obj.drawings) ? obj.drawings : [],\r\n };\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nconst HASH_KEY = 'tcw';\r\n\r\n/** Read a `#tcw=<encoded>` fragment from a URL hash, or null. */\r\nexport function readShareHash(hash: string): string | null {\r\n const clean = hash.startsWith('#') ? hash.slice(1) : hash;\r\n for (const part of clean.split('&')) {\r\n const eq = part.indexOf('=');\r\n if (eq > 0 && part.slice(0, eq) === HASH_KEY) return decodeURIComponent(part.slice(eq + 1));\r\n }\r\n return null;\r\n}\r\n\r\n/** Build a shareable URL by replacing the `tcw` hash param on `base`. */\r\nexport function buildShareUrl(base: string, encoded: string): string {\r\n const [withoutHash] = base.split('#');\r\n return `${withoutHash}#${HASH_KEY}=${encoded}`;\r\n}\r\n","/**\r\n * i18n for ChartWidget's own chrome (toolbar, watchlist, indicator picker,\r\n * status bar, settings panel, hotkey sheet). This does NOT translate\r\n * data-driven labels sourced from `widgetConfig.ts` (the 69 indicator\r\n * display names, drawing-tool names, timezone/locale option labels) — those\r\n * stay in English for now; see README \"Widget i18n\" for the current\r\n * coverage and how to extend it via `messages`.\r\n */\r\n\r\nexport type MessageKey = typeof EN_MESSAGES extends Record<infer K, string> ? K : never;\r\n\r\nexport const EN_MESSAGES = {\r\n // Toolbar\r\n 'toolbar.indicators': 'Indicators',\r\n 'toolbar.indicators.popular': 'Popular',\r\n 'toolbar.indicators.all': 'All',\r\n 'indicatorType.overlay': 'overlay',\r\n 'indicatorType.panel': 'panel',\r\n 'toolbar.replay': 'Bar replay',\r\n 'toolbar.longBracket': 'Long bracket',\r\n 'toolbar.shortBracket': 'Short bracket',\r\n 'toolbar.depthLadder': 'Depth ladder',\r\n 'toolbar.objects': 'Objects',\r\n 'toolbar.priceAlerts': 'Price alerts',\r\n 'toolbar.screenshot': 'Screenshot',\r\n 'toolbar.settings': 'Chart Settings',\r\n 'toolbar.toggleTheme': 'Toggle theme',\r\n\r\n // Chart types\r\n 'chartType.candlestick': 'Candlestick',\r\n 'chartType.line': 'Line',\r\n 'chartType.area': 'Area',\r\n 'chartType.bar': 'Bar',\r\n 'chartType.heikinAshi': 'Heikin-Ashi',\r\n 'chartType.hollowCandle': 'Hollow Candle',\r\n 'chartType.baseline': 'Baseline',\r\n 'chartType.volumeCandles': 'Volume Candles',\r\n 'chartType.equivolume': 'Equivolume',\r\n 'chartType.hlcArea': 'HLC Area',\r\n 'chartType.stepLine': 'Step Line',\r\n 'chartType.lineWithMarkers': 'Line + Markers',\r\n\r\n // Watchlist\r\n 'watchlist.title': 'Watchlist',\r\n\r\n // Status bar / connection\r\n 'status.connecting': 'Connecting...',\r\n 'status.live': 'Live',\r\n 'status.connectionFailed': 'Connection failed',\r\n 'status.loading': 'Loading chart...',\r\n\r\n // Settings panel\r\n 'settings.title': 'Chart Settings',\r\n 'settings.tab.style': 'style',\r\n 'settings.tab.display': 'display',\r\n 'settings.tab.scale': 'scale',\r\n 'settings.resetToDefaults': 'Reset to defaults',\r\n 'settings.done': 'Done',\r\n 'settings.section.candleColors': 'Candle Colors',\r\n 'settings.section.background': 'Background',\r\n\r\n // Hotkey sheet\r\n 'hotkeys.title': 'Keyboard shortcuts',\r\n 'hotkeys.close': 'Close',\r\n 'hotkeys.gotIt': 'Got it',\r\n 'hotkeys.group.searchNavigation': 'Search & navigation',\r\n 'hotkeys.group.chartManipulation': 'Chart manipulation',\r\n 'hotkeys.group.touch': 'Touch (mobile / tablet)',\r\n 'hotkeys.group.keyboard': 'Keyboard',\r\n 'hotkeys.group.drawing': 'Drawing',\r\n} as const;\r\n\r\nexport const VI_MESSAGES: Partial<Record<MessageKey, string>> = {\r\n 'toolbar.indicators': 'Chỉ báo',\r\n 'toolbar.indicators.popular': 'Phổ biến',\r\n 'toolbar.indicators.all': 'Tất cả',\r\n 'indicatorType.overlay': 'phủ lên',\r\n 'indicatorType.panel': 'bảng riêng',\r\n 'toolbar.replay': 'Phát lại',\r\n 'toolbar.longBracket': 'Lệnh Long',\r\n 'toolbar.shortBracket': 'Lệnh Short',\r\n 'toolbar.depthLadder': 'Sổ lệnh',\r\n 'toolbar.objects': 'Đối tượng',\r\n 'toolbar.priceAlerts': 'Cảnh báo giá',\r\n 'toolbar.screenshot': 'Chụp màn hình',\r\n 'toolbar.settings': 'Cài đặt biểu đồ',\r\n 'toolbar.toggleTheme': 'Đổi giao diện',\r\n\r\n 'chartType.candlestick': 'Nến',\r\n 'chartType.line': 'Đường',\r\n 'chartType.area': 'Vùng',\r\n 'chartType.bar': 'Thanh',\r\n 'chartType.heikinAshi': 'Heikin-Ashi',\r\n 'chartType.hollowCandle': 'Nến rỗng',\r\n 'chartType.baseline': 'Đường cơ sở',\r\n 'chartType.volumeCandles': 'Nến khối lượng',\r\n 'chartType.equivolume': 'Equivolume',\r\n 'chartType.hlcArea': 'Vùng HLC',\r\n 'chartType.stepLine': 'Đường bậc thang',\r\n 'chartType.lineWithMarkers': 'Đường + điểm đánh dấu',\r\n\r\n 'watchlist.title': 'Danh mục theo dõi',\r\n\r\n 'status.connecting': 'Đang kết nối...',\r\n 'status.live': 'Trực tiếp',\r\n 'status.connectionFailed': 'Kết nối thất bại',\r\n 'status.loading': 'Đang tải biểu đồ...',\r\n\r\n 'settings.title': 'Cài đặt biểu đồ',\r\n 'settings.tab.style': 'Giao diện',\r\n 'settings.tab.display': 'Hiển thị',\r\n 'settings.tab.scale': 'Thang giá',\r\n 'settings.resetToDefaults': 'Khôi phục mặc định',\r\n 'settings.done': 'Xong',\r\n 'settings.section.candleColors': 'Màu nến',\r\n 'settings.section.background': 'Nền',\r\n\r\n 'hotkeys.title': 'Phím tắt',\r\n 'hotkeys.close': 'Đóng',\r\n 'hotkeys.gotIt': 'Đã hiểu',\r\n 'hotkeys.group.searchNavigation': 'Tìm kiếm & điều hướng',\r\n 'hotkeys.group.chartManipulation': 'Thao tác biểu đồ',\r\n 'hotkeys.group.touch': 'Cảm ứng (di động / máy tính bảng)',\r\n 'hotkeys.group.keyboard': 'Bàn phím',\r\n 'hotkeys.group.drawing': 'Vẽ',\r\n};\r\n\r\nexport const BUILTIN_LOCALES: Record<string, Partial<Record<MessageKey, string>>> = {\r\n en: EN_MESSAGES,\r\n vi: VI_MESSAGES,\r\n};\r\n\r\n/**\r\n * Resolve the widget's message table: built-in English as the base, the\r\n * requested built-in locale layered on top (falling back key-by-key to\r\n * English for anything that locale hasn't translated yet), then host\r\n * `messages` overrides layered last so they always win.\r\n */\r\nexport function resolveMessages(\r\n locale: string | undefined,\r\n overrides: Partial<Record<MessageKey, string>> | undefined,\r\n): Record<MessageKey, string> {\r\n const base = { ...EN_MESSAGES } as Record<MessageKey, string>;\r\n const localeTable = locale ? BUILTIN_LOCALES[locale] : undefined;\r\n if (localeTable) Object.assign(base, localeTable);\r\n if (overrides) Object.assign(base, overrides);\r\n return base;\r\n}\r\n\r\nexport type Translator = (key: MessageKey) => string;\r\n\r\nexport function createTranslator(messages: Record<MessageKey, string>): Translator {\r\n return (key: MessageKey) => messages[key] ?? EN_MESSAGES[key] ?? key;\r\n}\r\n","/**\r\n * How long a symbol/timeframe switch may run before the loading veil\r\n * appears. Faster loads just swap the chart in place — flashing a loader for\r\n * a 150 ms request reads as flicker, not feedback.\r\n */\r\nexport const LOADING_SHOW_DELAY_MS = 200;\r\n\r\nconst SKELETON_BARS = 20;\r\n\r\n/**\r\n * TradingView-style loading state for the chart area.\r\n *\r\n * - First load (nothing to show yet): opaque skeleton, shown immediately.\r\n * - Switch (a chart is already on screen): the old chart stays visible and is\r\n * veiled only if the load outlasts `LOADING_SHOW_DELAY_MS`.\r\n * - Failure: the label becomes the error message until the next load or a\r\n * successful retry ends it.\r\n */\r\nexport class WidgetLoadingOverlay {\r\n private readonly el: HTMLDivElement;\r\n private readonly label: HTMLDivElement;\r\n private showTimer: ReturnType<typeof setTimeout> | null = null;\r\n // Starts loading: the widget mounts before its first bars arrive.\r\n private phase: 'idle' | 'loading' | 'failed' = 'loading';\r\n\r\n constructor(parent: HTMLElement, private readonly loadingText: string) {\r\n this.el = document.createElement('div');\r\n this.el.className = 'tcw-loading-overlay';\r\n this.el.setAttribute('role', 'status');\r\n this.el.setAttribute('aria-live', 'polite');\r\n\r\n // Bars + label share a card: transparent on the opaque first-load screen,\r\n // a raised panel when veiling a chart so it reads over the candles.\r\n const card = document.createElement('div');\r\n card.className = 'tcw-loading-card';\r\n\r\n const bars = document.createElement('div');\r\n bars.className = 'tcw-loading-bars';\r\n for (let i = 0; i < SKELETON_BARS; i++) {\r\n const bar = document.createElement('span');\r\n bar.className = 'tcw-loading-bar';\r\n bar.style.height = `${20 + Math.round(Math.sin(i * 0.9) * 18 + 18)}px`;\r\n bar.style.animationDelay = `${i * 45}ms`;\r\n bars.appendChild(bar);\r\n }\r\n card.appendChild(bars);\r\n\r\n this.label = document.createElement('div');\r\n this.label.className = 'tcw-loading-label';\r\n this.label.textContent = loadingText;\r\n card.appendChild(this.label);\r\n this.el.appendChild(card);\r\n\r\n parent.appendChild(this.el);\r\n }\r\n\r\n /**\r\n * Start a load. `hasContent`: a chart is already on screen to keep showing.\r\n * `immediate`: skip the show delay — the caller knows the load is slow.\r\n */\r\n begin(hasContent: boolean, immediate = false): void {\r\n this.phase = 'loading';\r\n this.clearTimer();\r\n this.label.textContent = this.loadingText;\r\n this.el.classList.remove('tcw-loading-overlay--error');\r\n this.el.classList.toggle('tcw-loading-overlay--veil', hasContent);\r\n if (!hasContent || immediate || this.isShown()) {\r\n this.el.classList.remove('tcw-loading-overlay--hidden');\r\n return;\r\n }\r\n this.showTimer = setTimeout(() => {\r\n this.showTimer = null;\r\n this.el.classList.remove('tcw-loading-overlay--hidden');\r\n }, LOADING_SHOW_DELAY_MS);\r\n }\r\n\r\n /** The load finished: fade out, or never appear if still within the delay. */\r\n end(): void {\r\n this.phase = 'idle';\r\n this.clearTimer();\r\n this.el.classList.add('tcw-loading-overlay--hidden');\r\n }\r\n\r\n /** The current load failed (a retry may still be running): show why. */\r\n fail(message: string): void {\r\n if (this.phase === 'idle') return;\r\n this.phase = 'failed';\r\n this.clearTimer();\r\n this.label.textContent = message;\r\n this.el.classList.add('tcw-loading-overlay--error');\r\n this.el.classList.remove('tcw-loading-overlay--hidden');\r\n }\r\n\r\n /** Whether a load is in progress (begun, not yet ended) — failed included. */\r\n isActive(): boolean {\r\n return this.phase !== 'idle';\r\n }\r\n\r\n /** Whether the current load failed and is waiting on a retry. */\r\n hasFailed(): boolean {\r\n return this.phase === 'failed';\r\n }\r\n\r\n /** Whether the overlay is on screen (or fading in). */\r\n isShown(): boolean {\r\n return !this.el.classList.contains('tcw-loading-overlay--hidden');\r\n }\r\n\r\n destroy(): void {\r\n this.clearTimer();\r\n this.el.remove();\r\n }\r\n\r\n private clearTimer(): void {\r\n if (this.showTimer !== null) {\r\n clearTimeout(this.showTimer);\r\n this.showTimer = null;\r\n }\r\n }\r\n}\r\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\nimport { resolveMessages, createTranslator, type Translator } from './i18n.js';\r\nimport { WidgetLoadingOverlay } from './WidgetLoadingOverlay.js';\r\n\r\n/**\r\n * A local timeframe switch (resampling static data) that took at least this\r\n * long last time is announced with the loading veil before it runs, since the\r\n * main thread is about to be busy for several frames.\r\n */\r\nconst SLOW_LOCAL_SWITCH_MS = 48;\r\n/** Base series this long are assumed slow to resample before any timing exists. */\r\nconst LARGE_SERIES_BARS = 50_000;\r\n\r\n/** Upper bound on waiting for a paint — rAF never fires in a frame that isn't rendering. */\r\nconst PAINT_WAIT_MAX_MS = 100;\r\n\r\n/** Resolve once the browser has painted the current DOM state (or gave up waiting). */\r\nfunction afterPaint(): Promise<void> {\r\n return new Promise((resolve) => {\r\n if (typeof requestAnimationFrame !== 'function' || document.hidden) {\r\n setTimeout(resolve, 0);\r\n return;\r\n }\r\n const fallback = setTimeout(resolve, PAINT_WAIT_MAX_MS);\r\n requestAnimationFrame(() => setTimeout(() => {\r\n clearTimeout(fallback);\r\n resolve();\r\n }, 0));\r\n });\r\n}\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 /** Per-symbol refPrice explicitly pushed by the host via `setWatchlistEntry` — takes precedence over `sessionRefPrice`. */\r\n private hostWatchlistRefPrice = new Map<string, number>();\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 loading: WidgetLoadingOverlay;\r\n /** Bumped per stream connect; a connect that is no longer the latest leaves the UI to the newer one. */\r\n private connectSeq = 0;\r\n /** Bumped per local resample and widget.setData; a deferred local switch that is no longer the latest is skipped. */\r\n private localSeq = 0;\r\n /** Duration of the last local resample + setData, for SLOW_LOCAL_SWITCH_MS. */\r\n private lastLocalSwitchMs = 0;\r\n private destroyed = false;\r\n private options: ChartWidgetOptions;\r\n private symbols: string[];\r\n private settingsState: ChartSettingsState;\r\n private t: Translator;\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 // `numberLocale` lives in two places: the headless Chart gets it via\r\n // `chartOptions` (spread straight into `new Chart()` below) — but the\r\n // widget's own chrome (watchlist, alerts, hotkey sheet, settings panel)\r\n // reads `settingsState.numberLocale`, which otherwise stays on\r\n // DEFAULT_SETTINGS' 'en-US' until the host touches the Settings UI.\r\n // Seed it from the same option so both layers start in sync.\r\n this.settingsState = {\r\n ...DEFAULT_SETTINGS,\r\n ...(options.chartOptions?.numberLocale ? { numberLocale: options.chartOptions.numberLocale } : {}),\r\n };\r\n this.t = createTranslator(resolveMessages(options.locale, options.messages));\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 // Static data (no adapter) has no connection to report.\r\n connectionState: options.adapter ? 'connecting' : 'disconnected',\r\n connectionMessage: options.adapter ? this.t('status.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 this.t,\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 // TradingView-style loading state: covers the empty chart until the first\r\n // bars land, then veils the previous chart during slow switches.\r\n this.loading = new WidgetLoadingOverlay(this.chartContainer, this.t('status.loading'));\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 }, this.t('watchlist.title'));\r\n this.watchlist.setActive(this.state.symbol);\r\n this.watchlist.setLocale(this.settingsState.numberLocale || undefined);\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 ...options.chartOptions,\r\n // `features` is merged explicitly (host overrides win per-key) rather\r\n // than inherited wholesale from the `...options.chartOptions` spread\r\n // above — otherwise passing e.g. `chartOptions: { features: { x } }`\r\n // would silently drop every other default below.\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 // TradingView itself has no cursor-following OHLCV popup — just the\r\n // legend, which ChartWidget already renders. Off by default here\r\n // (the headless Chart's own default stays `true`); opt back in via\r\n // `chartOptions: { features: { crosshairTooltip: true } }`.\r\n crosshairTooltip: false,\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 ...options.chartOptions?.features,\r\n },\r\n });\r\n\r\n // New bars end the loading state, whoever supplied them (stream snapshot,\r\n // widget.setData, or the host calling getChart().setData directly); stream\r\n // errors surface in the status bar and, mid-load, on the loading veil.\r\n this.chart.on('dataUpdate', (e) => this.handleDataUpdate(e.payload));\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 }, this.t);\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: () => {} }, this.t);\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 * A host-supplied `refPrice` takes precedence over the widget's own\r\n * session-open guess for that symbol — including the active one, so the\r\n * auto-tick loop stops clobbering it (see `tickWatchlist`).\r\n */\r\n setWatchlistEntry(symbol: string, entry: Partial<WatchlistEntry>): void {\r\n if (entry.refPrice !== undefined) {\r\n this.hostWatchlistRefPrice.set(symbol, entry.refPrice);\r\n }\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 const hostRef = this.hostWatchlistRefPrice.get(this.state.symbol);\r\n // Reference price: first bar of the loaded slice — that's the closest\r\n // approximation of \"session open\" without timezone bookkeeping. Only\r\n // used as a fallback; a refPrice the host already pushed via\r\n // `setWatchlistEntry` (even for the active symbol) always wins.\r\n if (hostRef === undefined && 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: hostRef ?? this.sessionRefPrice ?? data[0].open,\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 // Live adapter owns the data — refetch at the native resolution.\r\n await 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 await this.switchLocalTimeframe();\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.loading.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 void this.setTimeframe(tf);\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.localSeq++; // supersedes a local switch still waiting to run\r\n this.baseSeries = data;\r\n this.baseTimeframeMs = inferTimeframeMs(data);\r\n this.applyTimeframeData();\r\n // Static data is loaded the moment it's set, even an empty series. With a\r\n // live adapter the stream's own load decides (connectStream).\r\n if (!this.adapter) this.loading.end();\r\n }\r\n\r\n /**\r\n * Local timeframe switch. When it is expected to block the main thread for\r\n * several frames, veil the chart first and let that paint — otherwise the\r\n * click would look ignored until the new chart pops in.\r\n */\r\n private async switchLocalTimeframe(): Promise<void> {\r\n if (!this.baseSeries) return;\r\n const seq = ++this.localSeq;\r\n const expectSlow = this.lastLocalSwitchMs >= SLOW_LOCAL_SWITCH_MS\r\n || this.baseSeries.length >= LARGE_SERIES_BARS;\r\n try {\r\n if (expectSlow) {\r\n this.loading.begin(this.chart.getData().length > 0, true);\r\n await afterPaint();\r\n // Superseded: the newer switch or setData() ends the loading state.\r\n if (seq !== this.localSeq || this.destroyed) return;\r\n }\r\n this.applyTimeframeData();\r\n } finally {\r\n // Also on a throw (bad data, a failing custom indicator) — never leave\r\n // the veil up.\r\n if (seq === this.localSeq) this.loading.end();\r\n }\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 started = performance.now();\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 this.lastLocalSwitchMs = performance.now() - started;\r\n }\r\n\r\n private handleDataUpdate(payload: unknown): void {\r\n if (!payload || typeof payload !== 'object') return;\r\n const p = payload as { length?: number; error?: string; connection?: { state?: string } };\r\n if (typeof p.length === 'number') {\r\n if (p.length > 0 && this.loading.isActive()) {\r\n this.loading.end();\r\n // A retry after a failed load just delivered history.\r\n if (this.state.connectionState === 'error') this.setConnectionState('connected', this.t('status.live'));\r\n }\r\n return;\r\n }\r\n if (p.error !== undefined) {\r\n // Only a failed *load* is reported from the error itself. Errors outside\r\n // one can be transient (a single failed poll on a healthy connection);\r\n // the status bar follows the stream's connection state below instead.\r\n if (this.loading.isActive()) {\r\n this.loading.fail(this.t('status.connectionFailed'));\r\n this.setConnectionState('error', p.error || this.t('status.connectionFailed'));\r\n }\r\n return;\r\n }\r\n switch (p.connection?.state) {\r\n case 'connected':\r\n // A retry that brought back an empty history ends a failed load too.\r\n if (this.loading.hasFailed()) this.loading.end();\r\n if (!this.loading.isActive() && this.state.connectionState !== 'connected') {\r\n this.setConnectionState('connected', this.t('status.live'));\r\n }\r\n break;\r\n case 'reconnecting':\r\n if (!this.loading.isActive()) this.setConnectionState('connecting', this.t('status.connecting'));\r\n break;\r\n case 'error':\r\n if (!this.loading.isActive()) this.setConnectionState('error', this.t('status.connectionFailed'));\r\n break;\r\n }\r\n }\r\n\r\n private setConnectionState(connectionState: WidgetState['connectionState'], connectionMessage: string): void {\r\n this.state = { ...this.state, connectionState, connectionMessage };\r\n this.updateUI();\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 /** Open (or close) bar replay with its scrubber — what the toolbar's Replay button does. */\r\n 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) {\r\n this.chart.setNumberLocale(patch.numberLocale);\r\n this.watchlist?.setLocale(patch.numberLocale || undefined);\r\n }\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 const seq = ++this.connectSeq;\r\n\r\n this.state = {\r\n ...this.state,\r\n connectionState: 'connecting',\r\n connectionMessage: this.t('status.connecting'),\r\n };\r\n this.updateUI();\r\n // Keep the previous chart up while the next one loads; it only gets the\r\n // veil if the request is slow (see WidgetLoadingOverlay).\r\n this.loading.begin(this.chart.getData().length > 0);\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 // A newer switch started while this one was loading — it owns the UI now.\r\n if (seq !== this.connectSeq || this.destroyed) return;\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 if (this.loading.hasFailed()) {\r\n // History failed to load; the stream keeps retrying and the next\r\n // snapshot ends the loading state (handleDataUpdate).\r\n this.state = { ...this.state, connectionState: 'error' };\r\n } else {\r\n this.loading.end();\r\n this.state = {\r\n ...this.state,\r\n connectionState: 'connected',\r\n connectionMessage: this.t('status.live'),\r\n };\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 if (seq !== this.connectSeq || this.destroyed) return;\r\n this.loading.fail(this.t('status.connectionFailed'));\r\n this.state = {\r\n ...this.state,\r\n connectionState: 'error',\r\n connectionMessage: err instanceof Error ? err.message : this.t('status.connectionFailed'),\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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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../src/io/resampleOHLCV.ts","../../src/widget/widgetConfig.ts","../../src/widget/WidgetStyles.ts","../../src/widget/iconSet.ts","../../src/widget/icons.ts","../../src/widget/escapeHtml.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/widgetTimeframes.ts","../../src/widget/WidgetGoToDate.ts","../../src/widget/WidgetTooltip.ts","../../src/widget/WidgetIndicatorLegend.ts","../../src/widget/legendValues.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/i18n.ts","../../src/widget/WidgetLoadingOverlay.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 { DARK_THEME } from '@tradecanvas/commons';\nimport type { ChartType, DrawingToolType } from '@tradecanvas/commons';\nimport type { IndicatorDef, DrawingToolGroupDef, ChartSettingsState } from './types.js';\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 { label: 'Info Line', value: 'infoLine' as DrawingToolType },\n { label: 'Trend Angle', value: 'trendAngle' as DrawingToolType },\n ],\n },\n {\n label: 'Horizontal/Vertical',\n tools: [\n { label: 'Horizontal Line', value: 'horizontalLine' as DrawingToolType },\n { label: 'Horizontal Ray', value: 'horizontalRay' as DrawingToolType },\n { label: 'Vertical Line', value: 'verticalLine' as DrawingToolType },\n { label: 'Cross Line', value: 'crossLine' 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 { label: 'Fib Channel', value: 'fibChannel' as DrawingToolType },\n { label: 'Fib Time Zones', value: 'fibTimeZones' as DrawingToolType },\n { label: 'Fib Speed Resistance Fan', value: 'fibSpeedResistanceFan' as DrawingToolType },\n ],\n },\n {\n label: 'Shapes',\n tools: [\n { label: 'Rectangle', value: 'rectangle' as DrawingToolType },\n { label: 'Circle', value: 'circle' as DrawingToolType },\n { label: 'Ellipse', value: 'ellipse' as DrawingToolType },\n { label: 'Triangle', value: 'triangle' as DrawingToolType },\n ],\n },\n {\n label: 'Gann & Pitchforks',\n tools: [\n { label: 'Pitchfork', value: 'pitchfork' as DrawingToolType },\n { label: 'Schiff Pitchfork', value: 'schiffPitchfork' as DrawingToolType },\n { label: 'Modified Schiff Pitchfork', value: 'modifiedSchiffPitchfork' as DrawingToolType },\n { label: 'Gann Fan', value: 'gannFan' as DrawingToolType },\n { label: 'Gann Box', value: 'gannBox' as DrawingToolType },\n { label: 'Cyclic Lines', value: 'cyclicLines' as DrawingToolType },\n ],\n },\n {\n label: 'Patterns',\n tools: [\n { label: 'XABCD Pattern', value: 'xabcdPattern' as DrawingToolType },\n { label: 'ABCD Pattern', value: 'abcdPattern' as DrawingToolType },\n { label: 'Head and Shoulders', value: 'headAndShoulders' 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: 'Date and Price Range', value: 'dateAndPriceRange' 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: 'Price Label', value: 'priceLabel' as DrawingToolType },\n { label: 'Arrow', value: 'arrow' as DrawingToolType },\n ],\n },\n {\n label: 'Forecasting',\n tools: [\n { label: 'Long/Short Position', value: 'riskReward' as DrawingToolType },\n { label: 'Anchored VWAP', value: 'anchoredVWAP' as DrawingToolType },\n { label: 'Fixed Range Volume Profile', value: 'volumeProfileRange' 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: 'tema', name: 'Triple EMA', type: 'overlay' },\n { id: 'vwma', name: 'VWMA', type: 'overlay' },\n { id: 'wma', name: 'Weighted MA', 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: 'envelope', name: 'Envelope', 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: DARK_THEME.candleUp,\n candleDownColor: DARK_THEME.candleDown,\n candleUpWick: DARK_THEME.candleUpWick,\n candleDownWick: DARK_THEME.candleDownWick,\n backgroundColor: DARK_THEME.background,\n gridColor: DARK_THEME.grid,\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 invertScale: false,\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","/**\n * The TradeCanvas icon set, as in the \"TradeCanvas Icons\" Figma file: a 24 px\n * grid with 2 px padding, 1.75 px strokes with round caps and joins. Drawing\n * tools mark their anchor points (where you click to draw) with filled dots.\n */\nexport interface IconDef {\n /** Stroked path data. */\n d?: string;\n /** Dashed stroke, for guides. */\n dash?: string;\n /** Solid shapes, such as filled candle bodies. */\n fills?: readonly string[];\n /** An area filled at 22%. */\n soft?: string;\n /** Filled dots: [cx, cy, r = 1.75]. */\n dots?: readonly (readonly number[])[];\n}\n\n/** Toolbar, sidebar and panel glyphs. */\nexport const UI_ICONS: Readonly<Record<string, IconDef>> = {\n cursor: { d: 'M6 3.5L18.5 12.5L12.6 13.6L9.7 19.4z' }, // Cursor\n trendingUp: { d: 'M3 17L9 11L13 14.5L21 6.5M15 6.5H21V12.5' }, // Indicators / Long\n trendingDown: { d: 'M3 7L9 13L13 9.5L21 17.5M15 17.5H21V11.5' }, // Short\n minus: { d: 'M5 12H19' }, // Minus\n plus: { d: 'M12 5V19M5 12H19' }, // Plus\n penLine: { d: 'M14.5 5.5L18.5 9.5M4 20L5 15.5L15.8 4.7a2 2 0 0 1 2.83 0l.67.67a2 2 0 0 1 0 2.83L8.5 19z' }, // Draw\n zigzag: { d: 'M3 17L8 9L13 15L21 6' }, // Patterns\n hash: { d: 'M5 9H19M5 15H19M10 4L8.5 20M15.5 4L14 20' }, // Grid\n square: { d: 'M6.5 4.5h11a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2h-11a2 2 0 0 1-2-2v-11a2 2 0 0 1 2-2z' }, // Shape\n gitBranch: { d: 'M6 3V15M18 9a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM6 21a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM18 9a9 9 0 0 1-9 9' }, // Branch\n ruler: { d: 'M3.5 16.5L16.5 3.5L20.5 7.5L7.5 20.5zM6.5 13.5L8 15M9.5 10.5L11.5 12.5M12.5 7.5L14 9' }, // Measure\n type: { d: 'M6 6V4.5H18V6M12 4.5V19.5M9.5 19.5H14.5' }, // Text\n magnet: { d: 'M6 4V11a6 6 0 0 0 12 0V4M6 4h3.5v7a2.5 2.5 0 0 0 5 0V4H18M6 8h3.5M14.5 8H18' }, // Magnet\n undo: { d: 'M9 14L4 9L9 4M4 9H14.5a5.5 5.5 0 0 1 0 11H11' }, // Undo\n redo: { d: 'M15 14L20 9L15 4M20 9H9.5a5.5 5.5 0 0 0 0 11H13' }, // Redo\n trash: { d: 'M4 7H20M9.5 7V4.5h5V7M6.5 7l.8 12.2A1.5 1.5 0 0 0 8.8 20.6h6.4a1.5 1.5 0 0 0 1.5-1.4L17.5 7M10 11v6M14 11v6' }, // Delete\n camera: { d: 'M4.5 7.5h3L9 5h6l1.5 2.5h3A1.5 1.5 0 0 1 21 9v9.5a1.5 1.5 0 0 1-1.5 1.5h-15A1.5 1.5 0 0 1 3 18.5V9a1.5 1.5 0 0 1 1.5-1.5zM15.5 13.5a3.5 3.5 0 1 1-7 0 3.5 3.5 0 0 1 7 0z' }, // Screenshot\n settings: { d: 'M4 7H14M18 7H20M4 17H8M12 17H20M18 7a2 2 0 1 1-4 0 2 2 0 0 1 4 0zM12 17a2 2 0 1 1-4 0 2 2 0 0 1 4 0z' }, // Settings\n moon: { d: 'M20 14.5A8 8 0 1 1 9.5 4a6.5 6.5 0 0 0 10.5 10.5z' }, // Dark theme\n sun: { d: 'M16 12a4 4 0 1 1-8 0 4 4 0 0 1 8 0zM12 2.5v2M12 19.5v2M4.6 4.6l1.4 1.4M18 18l1.4 1.4M2.5 12h2M19.5 12h2M4.6 19.4L6 18M18 6l1.4-1.4' }, // Light theme\n chevronDown: { d: 'M6 9L12 15L18 9' }, // Expand\n chevronUp: { d: 'M6 15L12 9L18 15' }, // Collapse\n barChart: { d: 'M5 20V13M12 20V5M19 20V10' }, // Chart type\n x: { d: 'M6 6L18 18M18 6L6 18' }, // Close\n play: { d: 'M7 4.5v15L19.5 12z' }, // Play\n pause: { d: 'M8 5V19M16 5V19' }, // Pause\n stop: { d: 'M7.5 6h9A1.5 1.5 0 0 1 18 7.5v9a1.5 1.5 0 0 1-1.5 1.5h-9A1.5 1.5 0 0 1 6 16.5v-9A1.5 1.5 0 0 1 7.5 6z' }, // Stop\n receipt: { d: 'M6 3.5h12v17l-2-1.25-2 1.25-2-1.25-2 1.25-2-1.25-2 1.25zM9 8h6M9 12h6M9 16h3' }, // Orders\n bell: { d: 'M6 16.5V11a6 6 0 0 1 12 0v5.5l1.5 2H4.5zM10 20.5a2.2 2.2 0 0 0 4 0' }, // Alerts\n layers: { d: 'M12 3.5L21 8.5L12 13.5L3 8.5zM3 12.5L12 17.5L21 12.5M3 16.5L12 21.5L21 16.5' }, // Objects\n eye: { d: 'M2.5 12S6 5.5 12 5.5 21.5 12 21.5 12 18 18.5 12 18.5 2.5 12 2.5 12zM15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0z' }, // Show\n eyeOff: { d: 'M4 4L20 20M9.9 5.8A9.6 9.6 0 0 1 12 5.5c6 0 9.5 6.5 9.5 6.5a16 16 0 0 1-2.3 3.1M6.6 7.1C3.9 8.9 2.5 12 2.5 12S6 18.5 12 18.5a9.3 9.3 0 0 0 4.7-1.3M10 10.1a3 3 0 0 0 4 4' }, // Hide\n lock: { d: 'M7 10.5h10a2 2 0 0 1 2 2v6a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2v-6a2 2 0 0 1 2-2zM8 10.5V7.5a4 4 0 0 1 8 0v3' }, // Lock\n unlock: { d: 'M7 10.5h10a2 2 0 0 1 2 2v6a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2v-6a2 2 0 0 1 2-2zM8 10.5V7.5a4 4 0 0 1 7.7-1.5' }, // Unlock\n palette: { d: 'M12 3.5a8.5 8.5 0 0 0 0 17c1.1 0 1.6-.8 1.6-1.6 0-.5-.2-.9-.5-1.2a1.6 1.6 0 0 1 1.2-2.7h1.9a4.3 4.3 0 0 0 4.3-4.3C20.5 6.9 16.7 3.5 12 3.5z', dots: [[7.5, 11.5, 1.25], [9.5, 7.75, 1.25], [14, 7.25, 1.25]] }, // Style\n check: { d: 'M5 12.5L10 17.5L19 7' }, // Done\n maximize: { d: 'M8 4H5a1 1 0 0 0-1 1v3M16 4h3a1 1 0 0 1 1 1v3M20 16v3a1 1 0 0 1-1 1h-3M8 20H5a1 1 0 0 1-1-1v-3' }, // Fullscreen\n minimize: { d: 'M4 8h3a1 1 0 0 0 1-1V4M16 4v3a1 1 0 0 0 1 1h3M20 16h-3a1 1 0 0 0-1 1v3M8 20v-3a1 1 0 0 0-1-1H4' }, // Exit fullscreen\n repeat: { d: 'M17 3.5L20.5 7L17 10.5M3.5 11.5V10a3 3 0 0 1 3-3h14M7 20.5L3.5 17L7 13.5M20.5 12.5V14a3 3 0 0 1-3 3h-14' }, // Stay in drawing mode\n calendar: { d: 'M5.5 5h13a2 2 0 0 1 2 2v11.5a2 2 0 0 1-2 2h-13a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2zM3.5 10H20.5M8 3V7M16 3V7' }, // Go to date\n star: { d: 'M12 3.5L14.6 9L20.5 9.6L16 13.6L17.3 19.5L12 16.5L6.7 19.5L8 13.6L3.5 9.6L9.4 9z' }, // Favourite\n ladder: { d: 'M4 6H11M13 6H17M6 10H11M13 10H20M8 14H11M13 14H15M5 18H11M13 18H19' }, // Depth ladder\n};\n\n/** One per drawing tool, keyed by tool type. */\nexport const DRAWING_TOOL_ICONS: Readonly<Record<string, IconDef>> = {\n trendLine: { d: 'M5 18L19 6', dots: [[5, 18], [19, 6]] }, // Trend Line\n ray: { d: 'M5 17L21 5M17.5 4.81L21 5L20.2 8.41', dots: [[5, 17], [11, 12.5]] }, // Ray\n extendedLine: { d: 'M3 18.5L21 5M17.5 4.81L21 5L20.2 8.41M6.5 18.69L3 18.5L3.8 15.09', dots: [[9, 14], [15, 9.5]] }, // Extended Line\n infoLine: { d: 'M5 20L19 10M4.5 3.5h9a1 1 0 0 1 1 1v4a1 1 0 0 1-1 1h-9a1 1 0 0 1-1-1v-4a1 1 0 0 1 1-1zM6.5 6.5h5', dots: [[5, 20], [19, 10]] }, // Info Line\n trendAngle: { d: 'M5 18L19 7M5 18H20M11 18A6 6 0 0 0 9.71 14.29', dots: [[5, 18], [19, 7]] }, // Trend Angle\n horizontalLine: { d: 'M3 12H21', dots: [[12, 12]] }, // Horizontal Line\n horizontalRay: { d: 'M7 12H21M18.5 9.5L21 12L18.5 14.5', dots: [[7, 12]] }, // Horizontal Ray\n verticalLine: { d: 'M12 3V21', dots: [[12, 12]] }, // Vertical Line\n crossLine: { d: 'M3 12H21M12 3V21', dots: [[12, 12]] }, // Cross Line\n parallelChannel: { d: 'M3 15L15 5M9 19L21 9', dots: [[3, 15], [15, 5], [9, 19]] }, // Parallel Channel\n regressionChannel: { d: 'M3 12L21 4M3 20L21 12', dash: 'M3 16L21 8', dots: [[3, 16], [21, 8]] }, // Regression Channel\n fibRetracement: { d: 'M3 4H21M3 9H21M3 13H21M3 20H21', dots: [[5, 20], [19, 4]] }, // Fib Retracement\n fibExtension: { d: 'M3 20L8 10L12 16M14 4H21M14 8H21M14 12H21', dots: [[3, 20], [8, 10], [12, 16]] }, // Fib Extension\n fibChannel: { d: 'M3 9L21 3M3 13L21 7M3 16L21 10M3 21L21 15', dots: [[3, 21], [21, 15], [3, 9]] }, // Fib Channel\n fibTimeZones: { d: 'M3 4V20M6 4V20M9.5 4V20M14 4V20M20.5 4V20', dots: [[3, 20], [6, 20]] }, // Fib Time Zones\n fibSpeedResistanceFan: { d: 'M4 20L20 4M4 20L20 11M4 20L20 16M4 20L11 4', dash: 'M4 4H20V20', dots: [[4, 20], [20, 4]] }, // Fib Speed Resistance Fan\n rectangle: { d: 'M5.5 6h13A1.5 1.5 0 0 1 20 7.5v9a1.5 1.5 0 0 1-1.5 1.5h-13A1.5 1.5 0 0 1 4 16.5v-9A1.5 1.5 0 0 1 5.5 6z', dots: [[4, 6], [20, 18]] }, // Rectangle\n circle: { d: 'M19.5 12a7.5 7.5 0 1 1-15 0 7.5 7.5 0 0 1 15 0z', dots: [[12, 12], [19.5, 12]] }, // Circle\n ellipse: { d: 'M20.5 12c0 3-3.8 5.5-8.5 5.5S3.5 15 3.5 12 7.3 6.5 12 6.5s8.5 2.5 8.5 5.5z', dots: [[3.5, 12], [20.5, 12]] }, // Ellipse\n triangle: { d: 'M12 4.5L20 19H4z', dots: [[12, 4.5], [20, 19], [4, 19]] }, // Triangle\n pitchfork: { d: 'M4 20L16.75 3M7 9L11.5 3M13 15L21 4.33M7 9L13 15', dots: [[4, 20], [7, 9], [13, 15]] }, // Pitchfork\n schiffPitchfork: { d: 'M4 14.5L21 7.42M7 9L21 3.17M13 15L21 11.67M7 9L13 15', dash: 'M4 20V14.5', dots: [[4, 14.5], [7, 9], [13, 15]] }, // Schiff Pitchfork\n modifiedSchiffPitchfork: { d: 'M5.5 14.5L21 5.89M7 9L17.8 3M13 15L21 10.56M7 9L13 15', dash: 'M4 20L5.5 14.5', dots: [[5.5, 14.5], [7, 9], [13, 15]] }, // Modified Schiff Pitchfork\n gannFan: { d: 'M4 20L20 4M4 20L20 12M4 20L12 4M4 20L20 16.5M4 20L7.5 4', dots: [[4, 20], [20, 4]] }, // Gann Fan\n gannBox: { d: 'M4 4H20V20H4zM4 20L20 4M4 4L20 20M12 4V20', dots: [[4, 20], [20, 4]] }, // Gann Box\n cyclicLines: { d: 'M4 4V20M9 4V20M14 4V20M19 4V20', dots: [[4, 20], [9, 20]] }, // Cyclic Lines\n xabcdPattern: { d: 'M3 18L7 6L11 13L15 8L21 19', dash: 'M3 18L11 13L21 19', dots: [[3, 18], [7, 6], [11, 13], [15, 8], [21, 19]] }, // XABCD Pattern\n abcdPattern: { d: 'M4 19L9 8L13 14L20 4', dots: [[4, 19], [9, 8], [13, 14], [20, 4]] }, // ABCD Pattern\n headAndShoulders: { d: 'M3 19L6 11L8.5 15L12 5L15.5 15L18 11L21 19', dash: 'M4.5 15H19.5', dots: [[6, 11], [12, 5], [18, 11]] }, // Head and Shoulders\n elliottWave: { d: 'M3 19L6 13L8.5 16L14 6L16 10L21 4', dots: [[3, 19], [21, 4]] }, // Elliott Wave\n priceRange: { d: 'M5 4H19M5 20H19M12 6.5V17.5M9 9.5L12 6.5L15 9.5M9 14.5L12 17.5L15 14.5' }, // Price Range\n dateRange: { d: 'M4 5V19M20 5V19M6.5 12H17.5M9.5 9L6.5 12L9.5 15M14.5 9L17.5 12L14.5 15' }, // Date Range\n dateAndPriceRange: { d: 'M6 18V4M3 7L6 4L9 7M6 18H20M17 15L20 18L17 21', dash: 'M6 4H20V18' }, // Date and Price Range\n measure: { d: 'M3.5 16.5L16.5 3.5L20.5 7.5L7.5 20.5zM6.5 13.5L8 15M9.5 10.5L11.5 12.5M12.5 7.5L14 9' }, // Measure\n text: { d: 'M6 6V4.5H18V6M12 4.5V19.5M9.5 19.5H14.5' }, // Text\n priceLabel: { d: 'M9 5H19a1.5 1.5 0 0 1 1.5 1.5v11A1.5 1.5 0 0 1 19 19H9L3.5 12zM11 12H17' }, // Price Label\n arrow: { d: 'M5 19L19 5M10 5H19V14' }, // Arrow\n riskReward: { d: 'M5 12V4H19V12M3 12H21', dash: 'M5 12V18H19V12', dots: [[5, 12]] }, // Long/Short Position\n anchoredVWAP: { d: 'M4 18C9 17 12 10 20 7M4 20.5V18', dots: [[4, 18]] }, // Anchored VWAP\n volumeProfileRange: { d: 'M6 7H12M6 10.5H17M6 14H15M6 17.5H10', dash: 'M3.5 4V20M20.5 4V20', dots: [[3.5, 20], [20.5, 20]] }, // Fixed Range Volume Profile\n};\n\n/** One per chart type, keyed by chart type. */\nexport const CHART_TYPE_ICONS: Readonly<Record<string, IconDef>> = {\n candlestick: { d: 'M8 3.5V7M8 16V20.5M16 5V8.5M16 15.5V19', fills: ['M6.5 7h3a1 1 0 0 1 1 1v7a1 1 0 0 1-1 1h-3a1 1 0 0 1-1-1V8a1 1 0 0 1 1-1z', 'M14.5 8.5h3a1 1 0 0 1 1 1v5a1 1 0 0 1-1 1h-3a1 1 0 0 1-1-1v-5a1 1 0 0 1 1-1z'] }, // Candlestick\n hollowCandle: { d: 'M8 3.5V7M8 16V20.5M16 5V8.5M16 15.5V19M6.5 7h3a1 1 0 0 1 1 1v7a1 1 0 0 1-1 1h-3a1 1 0 0 1-1-1V8a1 1 0 0 1 1-1zM14.5 8.5h3a1 1 0 0 1 1 1v5a1 1 0 0 1-1 1h-3a1 1 0 0 1-1-1v-5a1 1 0 0 1 1-1z' }, // Hollow Candle\n heikinAshi: { d: 'M5.5 9.5V12M5.5 18V20M12 5.5V8M12 14V16M18.5 3V4.5M18.5 10.5V12.5', fills: ['M4 12h3a.5.5 0 0 1 .5.5v5a.5.5 0 0 1-.5.5H4a.5.5 0 0 1-.5-.5v-5A.5.5 0 0 1 4 12z', 'M10.5 8h3a.5.5 0 0 1 .5.5v5a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-5a.5.5 0 0 1 .5-.5z', 'M17 4.5h3a.5.5 0 0 1 .5.5v5a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5V5a.5.5 0 0 1 .5-.5z'] }, // Heikin-Ashi\n bar: { d: 'M8 4V20M5 8H8M8 16H11M16 6V18M13 15H16M16 9H19' }, // Bar (OHLC)\n volumeCandles: { d: 'M6.5 5V8M6.5 16V19M15.5 3.5V6M15.5 16V20', fills: ['M5.5 8h2a.5.5 0 0 1 .5.5v7a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1-.5-.5v-7a.5.5 0 0 1 .5-.5z', 'M11.5 6h8a.5.5 0 0 1 .5.5v9a.5.5 0 0 1-.5.5h-8a.5.5 0 0 1-.5-.5v-9a.5.5 0 0 1 .5-.5z'] }, // Volume Candles\n equivolume: { d: 'M4.5 10h2a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1v-6a1 1 0 0 1 1-1zM10 6h5a1 1 0 0 1 1 1v7a1 1 0 0 1-1 1h-5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1zM18.5 4h1a1 1 0 0 1 1 1v5a1 1 0 0 1-1 1h-1a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1z' }, // Equivolume\n line: { d: 'M3 17L8 11L12 14L21 5' }, // Line\n area: { d: 'M3 17L8 11L12 14L21 5', soft: 'M3 17L8 11L12 14L21 5V20H3z' }, // Area\n baseline: { d: 'M3 16L7 9L11 14L15 7L21 15', dash: 'M3 12H21' }, // Baseline\n hlcArea: { d: 'M3 9L8 6L13 9L21 4M3 15L8 13L13 16L21 11', dash: 'M3 12L8 9.5L13 12.5L21 7.5', soft: 'M3 9L8 6L13 9L21 4V11L13 16L8 13L3 15z' }, // HLC Area\n stepLine: { d: 'M3 18H8V12H12V15H16V7H21' }, // Step Line\n lineWithMarkers: { d: 'M4 17L9 10L14 14L20 6', dots: [[4, 17], [9, 10], [14, 14], [20, 6]] }, // Line with Markers\n};\n\nconst DOT_RADIUS = 1.75;\nconst SOFT_OPACITY = 0.22;\nconst markupCache = new WeakMap<IconDef, string>();\n\n/** The icon's SVG elements, drawn in `currentColor`. */\nfunction markup(icon: IconDef): string {\n const cached = markupCache.get(icon);\n if (cached) return cached;\n let s = '';\n if (icon.soft) s += `<path d=\"${icon.soft}\" fill=\"currentColor\" fill-opacity=\"${SOFT_OPACITY}\" stroke=\"none\"/>`;\n for (const f of icon.fills ?? []) s += `<path d=\"${f}\" fill=\"currentColor\" stroke=\"none\"/>`;\n if (icon.d) s += `<path d=\"${icon.d}\"/>`;\n if (icon.dash) s += `<path d=\"${icon.dash}\" stroke-dasharray=\"2 2.5\"/>`;\n for (const [cx, cy, r = DOT_RADIUS] of icon.dots ?? []) s += `<circle cx=\"${cx}\" cy=\"${cy}\" r=\"${r}\" fill=\"currentColor\" stroke=\"none\"/>`;\n markupCache.set(icon, s);\n return s;\n}\n\n/** The icon as an inline SVG string at `size` px, coloured by `currentColor`. */\nexport function iconSvg(icon: IconDef, size: number): string {\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=\"1.75\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\">${markup(icon)}</svg>`;\n}\n","import { CHART_TYPE_ICONS, DRAWING_TOOL_ICONS, UI_ICONS, iconSvg, type IconDef } from './iconSet.js';\n\nconst own = (map: Readonly<Record<string, IconDef>>, key: string): IconDef | undefined =>\n Object.prototype.hasOwnProperty.call(map, key) ? map[key] : undefined;\n\n/** An interface icon (toolbar, sidebar, panels) as inline SVG; '' for an unknown name. */\nexport function createIcon(name: string, size = 14): string {\n const icon = own(UI_ICONS, name);\n return icon ? iconSvg(icon, size) : '';\n}\n\n/** A drawing tool's own icon; a pen for a tool without one (e.g. from a plugin). */\nexport function createToolIcon(tool: string, size = 16): string {\n return iconSvg(own(DRAWING_TOOL_ICONS, tool) ?? UI_ICONS.penLine, size);\n}\n\n/** A chart type's icon; the generic chart glyph for a type without one. */\nexport function createChartTypeIcon(type: string, size = 14): string {\n return iconSvg(own(CHART_TYPE_ICONS, type) ?? UI_ICONS.barChart, size);\n}\n","/** Text made safe to put in HTML markup, attribute values included. */\nexport function escapeHtml(text: string): string {\n return text.replace(/[&<>\"']/g, (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '\"': '&quot;', \"'\": '&#39;' })[c]!);\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, TimeFrame } from '@tradecanvas/commons';\nimport type { ToolbarConfig, ToolbarCallbacks, WidgetState } from './types.js';\nimport { createChartTypeIcon, createIcon } from './icons.js';\nimport { escapeHtml as esc } from './escapeHtml.js';\nimport { WidgetDropdown } from './WidgetDropdown.js';\nimport type { Translator } from './i18n.js';\n\nexport class WidgetToolbar {\n private config: ToolbarConfig;\n private callbacks: ToolbarCallbacks;\n private t: Translator;\n private el: HTMLDivElement;\n private chartTypeDropdown: WidgetDropdown | null = null;\n private indicatorDropdown: WidgetDropdown | null = null;\n private tfGroup: HTMLDivElement | null = null;\n private tfDropdown: WidgetDropdown | null = null;\n private tfFavorites: TimeFrame[] = [];\n private tfRendered = '';\n private themeBtn: HTMLButtonElement | null = null;\n private fullscreenBtn: HTMLButtonElement | null = null;\n\n constructor(host: HTMLElement, config: ToolbarConfig, callbacks: ToolbarCallbacks, t: Translator) {\n this.config = config;\n this.callbacks = callbacks;\n this.t = t;\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: the favourites as buttons (plus the current one if it isn't\n // pinned); the menu lists them all, with a star to pin or unpin.\n this.tfFavorites = [...(config.timeframeFavorites ?? config.timeframes.map((tf) => tf.value))];\n this.tfGroup = document.createElement('div');\n this.tfGroup.className = 'tcw-toolbar-group';\n el.appendChild(this.tfGroup);\n if (callbacks.onToggleTimeframeFavorite && config.timeframes.length > 0) {\n const tfWrap = document.createElement('div');\n tfWrap.style.position = 'relative';\n tfWrap.style.display = 'inline-flex';\n const tfTrigger = document.createElement('button');\n tfTrigger.className = 'tcw-btn tcw-tf-more';\n tfTrigger.dataset.role = 'timeframes';\n tfTrigger.title = this.t('toolbar.timeframes');\n tfTrigger.setAttribute('aria-label', this.t('toolbar.timeframes'));\n tfTrigger.innerHTML = createIcon('chevronDown', 12);\n tfWrap.appendChild(tfTrigger);\n el.appendChild(tfWrap);\n this.tfDropdown = new WidgetDropdown(tfWrap, { width: '150px' });\n this.buildTimeframeMenu();\n }\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\n // Spacer\n el.appendChild(this.spacer());\n\n // Right side buttons\n if (callbacks.onToggleReplay) {\n const replayBtn = this.iconBtn('play', this.t('toolbar.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', this.t('toolbar.longBracket'), () => onBracket('buy'));\n longBtn.dataset.role = 'long';\n longBtn.classList.add('tcw-btn-long');\n el.appendChild(longBtn);\n const shortBtn = this.iconBtn('trendingDown', this.t('toolbar.shortBracket'), () => 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', this.t('toolbar.depthLadder'), callbacks.onToggleLadder);\n ladderBtn.dataset.role = 'ladder';\n el.appendChild(ladderBtn);\n }\n\n if (callbacks.onToggleObjects) {\n const objectsBtn = this.iconBtn('layers', this.t('toolbar.objects'), callbacks.onToggleObjects);\n objectsBtn.dataset.role = 'objects';\n el.appendChild(objectsBtn);\n }\n\n if (callbacks.onToggleAlerts) {\n const alertsBtn = this.iconBtn('bell', this.t('toolbar.priceAlerts'), callbacks.onToggleAlerts);\n alertsBtn.dataset.role = 'alerts';\n el.appendChild(alertsBtn);\n }\n\n const screenshotBtn = this.iconBtn('camera', this.t('toolbar.screenshot'), callbacks.onScreenshot);\n el.appendChild(screenshotBtn);\n\n const settingsBtn = this.iconBtn('settings', this.t('toolbar.settings'), callbacks.onSettings);\n el.appendChild(settingsBtn);\n\n this.themeBtn = this.iconBtn('moon', this.t('toolbar.toggleTheme'), callbacks.onToggleTheme);\n this.themeBtn.dataset.role = 'theme';\n el.appendChild(this.themeBtn);\n\n if (callbacks.onToggleFullscreen) {\n this.fullscreenBtn = this.iconBtn('maximize', this.t('toolbar.fullscreen'), callbacks.onToggleFullscreen);\n this.fullscreenBtn.dataset.role = 'fullscreen';\n this.fullscreenBtn.setAttribute('aria-pressed', 'false');\n el.appendChild(this.fullscreenBtn);\n }\n }\n\n /** Swap the fullscreen button between enter and exit. */\n setFullscreen(on: boolean): void {\n if (!this.fullscreenBtn) return;\n const label = this.t(on ? 'toolbar.exitFullscreen' : 'toolbar.fullscreen');\n this.fullscreenBtn.innerHTML = createIcon(on ? 'minimize' : 'maximize', 14);\n this.fullscreenBtn.title = label;\n this.fullscreenBtn.setAttribute('aria-pressed', String(on));\n }\n\n private chartTypeLabel(ct: { value: ChartType; label: string }): string {\n const key = `chartType.${ct.value}` as const;\n const translated = this.t(key as Parameters<Translator>[0]);\n return translated === key ? ct.label : translated;\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 tcw-dropdown-item--icon\" data-ct=\"${esc(ct.value)}\">${createChartTypeIcon(ct.value, 16)}<span>${esc(this.chartTypeLabel(ct))}</span></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 /** Re-pin after the user starred or unstarred a timeframe. */\n setTimeframeFavorites(favorites: TimeFrame[]): void {\n this.tfFavorites = [...favorites];\n this.tfRendered = '';\n this.buildTimeframeMenu();\n }\n\n private buildTimeframeMenu(): void {\n if (!this.tfDropdown) return;\n const pin = esc(this.t('toolbar.timeframes.pin'));\n let html = `<div class=\"tcw-dropdown-label\">${esc(this.t('toolbar.timeframes'))}</div>`;\n for (const tf of this.config.timeframes) {\n const pinned = this.tfFavorites.includes(tf.value);\n const [value, label] = [esc(tf.value), esc(tf.label)];\n html += `<div class=\"tcw-tf-row\">`\n + `<button class=\"tcw-dropdown-item\" data-tf-pick=\"${value}\">${label}</button>`\n + `<button class=\"tcw-tf-star${pinned ? ' tcw-active' : ''}\" data-tf-star=\"${value}\" aria-pressed=\"${pinned}\"`\n + ` title=\"${pin}\" aria-label=\"${pin}: ${label}\">${createIcon('star', 12)}</button>`\n + `</div>`;\n }\n this.tfDropdown.setContent(html);\n\n const panel = this.tfDropdown['panel'] as HTMLDivElement;\n panel.querySelectorAll<HTMLButtonElement>('[data-tf-pick]').forEach((btn) => {\n btn.addEventListener('click', () => this.callbacks.onTimeframe(btn.dataset.tfPick as TimeFrame));\n });\n panel.querySelectorAll<HTMLButtonElement>('[data-tf-star]').forEach((btn) => {\n btn.addEventListener('click', (e) => {\n e.stopPropagation(); // pinning keeps the menu open\n this.callbacks.onToggleTimeframeFavorite?.(btn.dataset.tfStar as TimeFrame);\n });\n });\n }\n\n private renderTimeframes(current: TimeFrame): void {\n if (!this.tfGroup) return;\n const shown = this.config.timeframes.filter((tf) => this.tfFavorites.includes(tf.value) || tf.value === current);\n const key = `${shown.map((tf) => tf.value).join(',')}|${current}`;\n if (key === this.tfRendered) return;\n this.tfRendered = key;\n\n this.tfGroup.replaceChildren(...shown.map((tf) => {\n const btn = document.createElement('button');\n btn.className = 'tcw-btn';\n btn.textContent = tf.label;\n btn.dataset.tf = tf.value;\n btn.classList.toggle('tcw-active', tf.value === current);\n btn.addEventListener('click', () => this.callbacks.onTimeframe(tf.value));\n return btn;\n }));\n const panel = this.tfDropdown?.['panel'] as HTMLDivElement | undefined;\n panel?.querySelectorAll<HTMLButtonElement>('[data-tf-pick]').forEach((btn) => {\n btn.classList.toggle('tcw-active', btn.dataset.tfPick === current);\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 const typeLabel = (type: string) => this.t(`indicatorType.${type}` as Parameters<Translator>[0]);\n\n const row = (ind: (typeof indicators)[number]) =>\n `<button class=\"tcw-dropdown-item\" data-ind=\"${esc(ind.id)}\"><span>${esc(ind.name)}</span><span class=\"tcw-tag\">${esc(typeLabel(ind.type))}</span></button>`;\n let html = `<div class=\"tcw-dropdown-label\">${esc(this.t('toolbar.indicators.popular'))}</div>`;\n for (const ind of popular) html += row(ind);\n html += '<div class=\"tcw-dropdown-divider\"></div>';\n html += `<div class=\"tcw-dropdown-label\">${esc(this.t('toolbar.indicators.all'))}</div>`;\n for (const ind of other) html += row(ind);\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 this.renderTimeframes(state.timeframe);\n\n // Chart type trigger label\n const ctTrigger = this.el.querySelector('[data-role=\"charttype\"]') as HTMLElement | null;\n if (ctTrigger) {\n const ct = this.config.chartTypes.find(ct => ct.value === state.chartType);\n const label = ct ? this.chartTypeLabel(ct) : state.chartType;\n ctTrigger.innerHTML = `${createChartTypeIcon(state.chartType, 14)} ${esc(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)} ${this.t('toolbar.indicators')}`;\n if (count > 0) {\n inner += ` <span class=\"tcw-badge-count\">${count}</span>`;\n }\n indTrigger.innerHTML = inner;\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 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 { DrawingToolType } from '@tradecanvas/commons';\nimport type { SidebarConfig, SidebarCallbacks, WidgetState } from './types.js';\nimport { createIcon, createToolIcon } from './icons.js';\n\n/** Drawing tool icons carry more detail than interface glyphs: a size up. */\nconst TOOL_ICON_PX = 16;\n\n/** How long a tool menu stays after the pointer leaves it. */\nconst FLYOUT_CLOSE_DELAY_MS = 150;\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 /** Per group, the icon holder in its button and the tool it stands for (the last one used). */\n private groupIcons: HTMLSpanElement[] = [];\n private groupTools: DrawingToolType[] = [];\n private cursorBtn: HTMLButtonElement | null = null;\n private magnetBtn: HTMLButtonElement | null = null;\n private stayBtn: HTMLButtonElement | null = null;\n private flyoutEl: HTMLDivElement | null = null;\n private flyoutIdx = -1;\n private flyoutHideTimer: ReturnType<typeof setTimeout> | 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 // The group shows, and picks, its last used tool — the first until then.\n const tool = group.tools[0]?.value;\n if (!tool) return;\n // A group with a menu names itself in the menu's header: no tooltip on top of it.\n if (group.tools.length > 1) btn.setAttribute('aria-label', `${group.label}: ${group.tools[0].label}`);\n else btn.title = group.label;\n const icon = document.createElement('span');\n icon.className = 'tcw-sidebar-icon';\n icon.innerHTML = createToolIcon(tool, TOOL_ICON_PX);\n btn.appendChild(icon);\n this.groupIcons.push(icon);\n this.groupTools.push(tool);\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(this.groupTools[idx]));\n wrap.appendChild(btn);\n\n // Flyout events via JS (not CSS hover); keyboard focus opens it too.\n wrap.addEventListener('mouseenter', () => this.showFlyout(idx));\n wrap.addEventListener('mouseleave', () => this.scheduleHideFlyout());\n btn.addEventListener('focus', () => { if (btn.matches(':focus-visible')) this.showFlyout(idx); });\n wrap.addEventListener('focusout', (e) => {\n if (!wrap.contains(e.relatedTarget as Node | null)) this.scheduleHideFlyout();\n });\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 if (callbacks.onToggleMagnet) {\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\n if (callbacks.onToggleStayInDrawing) {\n this.stayBtn = document.createElement('button');\n this.stayBtn.className = 'tcw-sidebar-btn';\n this.stayBtn.dataset.role = 'stay';\n this.stayBtn.title = 'Stay in drawing mode';\n this.stayBtn.setAttribute('aria-pressed', 'false');\n this.stayBtn.innerHTML = createIcon('repeat', 14);\n this.stayBtn.addEventListener('click', callbacks.onToggleStayInDrawing);\n el.appendChild(this.stayBtn);\n }\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 = createToolIcon(tool, TOOL_ICON_PX);\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 this.cancelHideFlyout();\n if (this.flyoutEl && this.flyoutIdx === idx) return; // back before it closed: keep it\n const group = this.config.drawingToolGroups[idx];\n if (!group || group.tools.length <= 1) {\n this.hideFlyout();\n return;\n }\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.innerHTML = createToolIcon(tool.value, TOOL_ICON_PX);\n const name = document.createElement('span');\n name.textContent = tool.label;\n item.appendChild(name);\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.addEventListener('contextmenu', (e) => {\n e.preventDefault();\n this.callbacks.onToggleFavorite?.(tool.value);\n });\n }\n flyout.appendChild(item);\n }\n if (this.callbacks.onToggleFavorite) {\n // Said once for the menu rather than as a tooltip on every row.\n const hint = document.createElement('div');\n hint.className = 'tcw-flyout-hint';\n hint.textContent = 'Right-click a tool to pin it';\n flyout.appendChild(hint);\n }\n\n this.flyoutEl = flyout;\n this.flyoutIdx = idx;\n this.groupWraps[idx].appendChild(flyout);\n }\n\n /**\n * Close a moment after the pointer leaves, so one that slips off the menu\n * on its way to an item (a diagonal move) doesn't lose it.\n */\n private scheduleHideFlyout(): void {\n this.cancelHideFlyout();\n this.flyoutHideTimer = setTimeout(() => {\n this.flyoutHideTimer = null;\n this.hideFlyout();\n }, FLYOUT_CLOSE_DELAY_MS);\n }\n\n private cancelHideFlyout(): void {\n if (this.flyoutHideTimer === null) return;\n clearTimeout(this.flyoutHideTimer);\n this.flyoutHideTimer = null;\n }\n\n private hideFlyout(): void {\n this.cancelHideFlyout();\n if (this.flyoutEl) {\n this.flyoutEl.remove();\n this.flyoutEl = null;\n }\n this.flyoutIdx = -1;\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: the active group lights up and takes on the picked tool's icon.\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 if (isActive && state.activeTool && state.activeTool !== this.groupTools[i]) {\n this.groupTools[i] = state.activeTool;\n this.groupIcons[i].innerHTML = createToolIcon(state.activeTool, TOOL_ICON_PX);\n if (drawingToolGroups[i].tools.length > 1) {\n this.groupButtons[i].setAttribute('aria-label', `${drawingToolGroups[i].label}: ${toolLabel(drawingToolGroups, state.activeTool)}`);\n }\n }\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 if (this.stayBtn) {\n this.stayBtn.classList.toggle('tcw-active', state.stayInDrawing);\n this.stayBtn.setAttribute('aria-pressed', String(state.stayInDrawing));\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';\nimport type { Translator } from './i18n.js';\n\ntype Tab = 'style' | 'display' | 'scale';\nconst TABS: Tab[] = ['style', 'display', 'scale'];\n\nexport class WidgetSettings {\n private callbacks: SettingsCallbacks;\n private t: Translator;\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 /**\n * `barCountdown` / `logScale` false leave out the controls for features the\n * chart has switched off.\n */\n constructor(\n callbacks: SettingsCallbacks,\n t: Translator,\n private readonly available: { barCountdown?: boolean; logScale?: boolean } = {},\n /** Where the panel mounts (the widget's portal: themed, and inside it when fullscreen). */\n private readonly host: () => HTMLElement = () => document.body,\n ) {\n this.callbacks = callbacks;\n this.t = t;\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 this.host().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 = this.t('settings.title');\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 = this.t(`settings.tab.${tab}` as Parameters<Translator>[0]);\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 = this.t('settings.resetToDefaults');\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 = this.t('settings.done');\n doneBtn.addEventListener('click', () => {\n this.callbacks.onClose();\n this.close();\n });\n footer.appendChild(doneBtn);\n this.modal.appendChild(footer);\n\n this.host().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(this.t('settings.section.candleColors'));\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(this.t('settings.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 if (this.available.barCountdown !== false) {\n section.appendChild(this.toggleRow('Bar Countdown', s.barCountdown, (v) => this.patch({ barCountdown: v })));\n }\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.toggleRow('Invert Scale (Alt+I)', s.invertScale, (v) => this.patch({ invertScale: v })));\n const scales = [\n { value: 'regular', label: 'Regular' },\n { value: 'logarithmic', label: 'Logarithmic' },\n { value: 'percentage', label: 'Percentage' },\n { value: 'indexedTo100', label: 'Indexed to 100' },\n ].filter((o) => o.value !== 'logarithmic' || this.available.logScale !== false);\n section.appendChild(this.selectRow('Price Scale', s.scaleMode, scales,\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","import type { RangePreset } from '@tradecanvas/core';\nimport { createIcon } from './icons.js';\n\nexport interface StatusBarRange {\n presets: readonly RangePreset[];\n /** Button text per preset; the preset itself when missing. */\n presetLabels?: Partial<Record<RangePreset, string>>;\n groupLabel: string;\n goToLabel: string;\n onPreset: (preset: RangePreset) => void;\n onGoTo: () => void;\n}\n\n/**\n * Bottom bar: range presets and \"go to date\" on the left (when `range` is\n * given), connection state and symbol on the right.\n */\nexport class WidgetStatusBar {\n private el: HTMLDivElement;\n private dotEl: HTMLSpanElement;\n private messageEl: HTMLSpanElement;\n private infoEl: HTMLSpanElement;\n\n constructor(host: HTMLElement, range?: StatusBarRange) {\n this.el = document.createElement('div');\n this.el.className = 'tcw-statusbar';\n\n if (range) this.el.appendChild(this.buildRange(range));\n\n const right = document.createElement('div');\n right.className = 'tcw-status-right';\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 right.appendChild(indicator);\n\n this.infoEl = document.createElement('span');\n this.infoEl.className = 'tcw-status-info';\n right.appendChild(this.infoEl);\n\n this.el.appendChild(right);\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 private buildRange(range: StatusBarRange): HTMLDivElement {\n const group = document.createElement('div');\n group.className = 'tcw-range-bar';\n group.setAttribute('role', 'group');\n group.setAttribute('aria-label', range.groupLabel);\n\n for (const preset of range.presets) {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'tcw-range-btn';\n btn.dataset.range = preset;\n btn.textContent = range.presetLabels?.[preset] ?? preset;\n btn.addEventListener('click', () => range.onPreset(preset));\n group.appendChild(btn);\n }\n\n const goTo = document.createElement('button');\n goTo.type = 'button';\n goTo.className = 'tcw-range-btn tcw-range-goto';\n goTo.dataset.role = 'goto';\n goTo.title = `${range.goToLabel} (Alt+G)`;\n goTo.setAttribute('aria-label', range.goToLabel);\n goTo.innerHTML = createIcon('calendar', 13);\n goTo.addEventListener('click', range.onGoTo);\n group.appendChild(goTo);\n return group;\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 /** Where the overlay mounts (the widget's portal: themed, and inside it when fullscreen). */\n constructor(\n callbacks: CommandPaletteCallbacks,\n private readonly host: () => HTMLElement = () => document.body,\n ) {\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 this.host().append(this.backdrop, 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","import { escapeHtml } from './escapeHtml.js';\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 /** Where the overlay mounts (the widget's portal: themed, and inside it when fullscreen). */\n constructor(\n callbacks: SymbolSearchCallbacks,\n private readonly host: () => HTMLElement = () => document.body,\n ) {\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 this.host().append(this.backdrop, 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\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","import type { MessageKey, Translator } from './i18n.js';\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 polished desktop tools all ship.\n */\nexport interface HotkeySheetCallbacks {\n onClose: () => void;\n}\n\n// Group titles translate via this lookup; individual shortcut labels (and\n// the `keys` badges) stay English for now — see README \"Widget i18n\".\nconst GROUP_TITLE_KEYS: Record<string, MessageKey> = {\n 'Search & navigation': 'hotkeys.group.searchNavigation',\n 'Chart manipulation': 'hotkeys.group.chartManipulation',\n 'Touch (mobile / tablet)': 'hotkeys.group.touch',\n 'Keyboard': 'hotkeys.group.keyboard',\n 'Drawing': 'hotkeys.group.drawing',\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: ['Alt', 'G'], label: 'Go to date' },\n { keys: ['Alt', 'I'], label: 'Invert price scale' },\n { keys: ['?'], label: 'Show this sheet' },\n ],\n },\n {\n title: 'Chart manipulation',\n entries: [\n { keys: ['Drag'], label: 'Pan — past the last bar into empty future space' },\n { keys: [mod, 'Drag'], label: 'Select drawings in a box' },\n { keys: [mod, 'Click'], label: 'Add / remove a drawing from the selection' },\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 { keys: [mod, 'C'], label: 'Copy selected drawings' },\n { keys: [mod, 'V'], label: 'Paste drawings (into any chart on the page)' },\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 t: Translator;\n private boundKeydown: (e: KeyboardEvent) => void;\n\n /** Where the overlay mounts (the widget's portal: themed, and inside it when fullscreen). */\n constructor(\n callbacks: HotkeySheetCallbacks,\n t: Translator,\n private readonly host: () => HTMLElement = () => document.body,\n ) {\n this.callbacks = callbacks;\n this.t = t;\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>${this.t('hotkeys.title')}</h3>`;\n const closeBtn = document.createElement('button');\n closeBtn.className = 'tcw-modal-close';\n closeBtn.setAttribute('aria-label', this.t('hotkeys.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 const titleKey = GROUP_TITLE_KEYS[group.title];\n title.textContent = titleKey ? this.t(titleKey) : 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 = this.t('hotkeys.gotIt');\n ok.addEventListener('click', () => this.close());\n footer.appendChild(ok);\n this.modal.appendChild(footer);\n\n this.host().append(this.backdrop, 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","import { escapeHtml } from './escapeHtml.js';\n/**\n * Replay control bar. Surfaces the chart's replay engine as a floating\n * bottom-of-chart control and reports user intent through callbacks (no\n * chart coupling — the host calls chart.replayStart() / replayPause() / …).\n *\n * Two modes: `select` (pick the start bar: a hint, \"random bar\", play from a\n * default start) and `replay` (step, play/pause, scrub, speed). \"Back to\n * realtime\" is always there and is highlighted once the replay reaches the\n * last bar.\n */\nexport interface ReplayBarCallbacks {\n onPlay: () => void;\n onPause: () => void;\n onStepBack: () => void;\n onStepForward: () => void;\n onSeek: (index: number) => void;\n /** Bars revealed per second. */\n onSpeedChange: (barsPerSecond: number) => void;\n onRandomStart: () => void;\n onClose: () => void;\n}\n\nexport interface ReplayBarLabels {\n selectHint: string;\n random: string;\n realtime: string;\n barsPerSecond: string;\n play: string;\n pause: string;\n stepBack: string;\n stepForward: string;\n}\n\nexport const DEFAULT_REPLAY_LABELS: ReplayBarLabels = {\n selectHint: 'Click a bar to start the replay',\n random: 'Random bar',\n realtime: 'Back to realtime',\n barsPerSecond: 'bars/s',\n play: 'Play',\n pause: 'Pause',\n stepBack: 'Step back (Shift+←)',\n stepForward: 'Step forward (Shift+→)',\n};\n\nexport type ReplayBarState = 'playing' | 'paused' | 'stopped';\nexport type ReplayBarMode = 'select' | 'replay';\n\n/** Replay speeds, in bars revealed per second. */\nexport const REPLAY_SPEEDS = [1, 2, 3, 5, 10, 25, 50] as const;\nexport const DEFAULT_REPLAY_SPEED = 5;\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 realtimeBtn: HTMLButtonElement | null = null;\n private state: ReplayBarState = 'stopped';\n private mode: ReplayBarMode = 'select';\n private ended = false;\n private total = 0;\n private speed = DEFAULT_REPLAY_SPEED;\n private readonly labels: ReplayBarLabels;\n\n constructor(private readonly callbacks: ReplayBarCallbacks, labels: Partial<ReplayBarLabels> = {}) {\n this.labels = { ...DEFAULT_REPLAY_LABELS, ...labels };\n }\n\n mount(host: HTMLElement, opts: { total: number; speed?: number; mode?: ReplayBarMode }): void {\n if (this.root) return;\n this.total = Math.max(0, opts.total);\n this.speed = opts.speed ?? DEFAULT_REPLAY_SPEED;\n this.state = 'paused';\n this.mode = opts.mode ?? 'select';\n\n this.root = document.createElement('div');\n this.root.className = 'tcw-replay-bar';\n this.root.setAttribute('role', 'toolbar');\n this.root.setAttribute('aria-label', 'Replay');\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.realtimeBtn = null;\n this.state = 'stopped';\n this.ended = false;\n }\n\n isMounted(): boolean {\n return this.root !== null;\n }\n\n getMode(): ReplayBarMode {\n return this.mode;\n }\n\n setMode(mode: ReplayBarMode): void {\n // The button that started the replay (Random, Play) is about to hide:\n // keep keyboard focus inside the bar, on Play.\n const hadFocus = !!this.root?.contains(document.activeElement);\n this.mode = mode;\n this.syncUi();\n if (hadFocus && mode === 'replay') this.playBtn?.focus();\n }\n\n setState(state: ReplayBarState): void {\n this.state = state;\n this.syncUi();\n }\n\n /** The replay sits on its last bar: nothing left to play. */\n setEnded(ended: boolean): void {\n if (this.ended === ended) return;\n this.ended = ended;\n this.syncUi();\n }\n\n /** `current`: index of the bar on screen. */\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 = `${Math.min(current + 1, total)} / ${total}`;\n }\n }\n\n destroy(): void {\n this.unmount();\n }\n\n private markup(): string {\n const l = this.labels;\n const speeds = REPLAY_SPEEDS.map(\n (s) => `<option value=\"${s}\"${s === this.speed ? ' selected' : ''}>${s} ${escapeHtml(l.barsPerSecond)}</option>`,\n ).join('');\n return `\n <span class=\"tcw-replay-group\" data-mode=\"select\">\n <span class=\"tcw-replay-hint\" role=\"status\">${svgCursor()}${escapeHtml(l.selectHint)}</span>\n <button class=\"tcw-replay-text-btn\" data-act=\"random\">${escapeHtml(l.random)}</button>\n </span>\n <span class=\"tcw-replay-group\" data-mode=\"replay\">\n <button class=\"tcw-replay-btn\" data-act=\"stepBack\" title=\"${escapeHtml(l.stepBack)}\" aria-label=\"${escapeHtml(l.stepBack)}\">${svgStepBack()}</button>\n <button class=\"tcw-replay-btn tcw-replay-play\" data-act=\"play\" title=\"${escapeHtml(l.play)}\" aria-label=\"${escapeHtml(l.play)}\">${svgPlay()}</button>\n <button class=\"tcw-replay-btn\" data-act=\"stepForward\" title=\"${escapeHtml(l.stepForward)}\" aria-label=\"${escapeHtml(l.stepForward)}\">${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\" aria-label=\"Replay position\" />\n <span class=\"tcw-replay-progress\" data-tcw=\"progress\">1 / ${this.total}</span>\n <select class=\"tcw-replay-speed\" data-act=\"speed\" aria-label=\"Speed\">${speeds}</select>\n </span>\n <button class=\"tcw-replay-text-btn tcw-replay-realtime\" data-act=\"realtime\">${escapeHtml(l.realtime)}</button>\n `;\n }\n\n private wireEvents(): void {\n const root = this.root;\n if (!root) return;\n this.scrubber = root.querySelector('input[data-act=\"seek\"]');\n this.progressLabel = root.querySelector('[data-tcw=\"progress\"]');\n this.playBtn = root.querySelector('button[data-act=\"play\"]');\n this.realtimeBtn = root.querySelector('button[data-act=\"realtime\"]');\n\n this.realtimeBtn?.addEventListener('click', () => this.callbacks.onClose());\n root.querySelector('[data-act=\"random\"]')?.addEventListener('click', () => this.callbacks.onRandomStart());\n root.querySelector('[data-act=\"stepBack\"]')?.addEventListener('click', () => this.callbacks.onStepBack());\n root.querySelector('[data-act=\"stepForward\"]')?.addEventListener('click', () => this.callbacks.onStepForward());\n this.playBtn?.addEventListener('click', () => {\n if (this.state === 'playing') this.callbacks.onPause();\n else this.callbacks.onPlay();\n });\n this.scrubber?.addEventListener('input', () => this.callbacks.onSeek(Number(this.scrubber!.value)));\n (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 const root = this.root;\n if (!root) return;\n for (const group of root.querySelectorAll<HTMLElement>('.tcw-replay-group')) {\n group.hidden = group.dataset.mode !== this.mode;\n }\n root.classList.toggle('tcw-replay-bar--ended', this.ended);\n if (this.playBtn) {\n const playing = this.state === 'playing';\n this.playBtn.innerHTML = playing ? svgPause() : svgPlay();\n this.playBtn.title = playing ? this.labels.pause : this.labels.play;\n this.playBtn.setAttribute('aria-label', this.playBtn.title);\n const disable = this.ended && !playing;\n if (disable && document.activeElement === this.playBtn) this.realtimeBtn?.focus();\n this.playBtn.disabled = disable;\n }\n }\n}\n\n\nfunction svgPlay(): string {\n return '<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"currentColor\" aria-hidden=\"true\"><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\" aria-hidden=\"true\"><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\" aria-hidden=\"true\"><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\" aria-hidden=\"true\"><path d=\"M4 6l11 6L4 18V6zM16 6h2v12h-2z\"/></svg>';\n}\nfunction svgCursor(): string {\n return '<svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" aria-hidden=\"true\"><path d=\"M12 3v18M8 7l4-4 4 4M8 17l4 4 4-4\"/></svg>';\n}\n","/**\r\n * Watchlist sidebar — vertical list of symbols, each with last price, %\r\n * change, and a mini sparkline. Clicking switches the chart's symbol.\r\n *\r\n * The widget tracks the *active* symbol's price/spark automatically from the\r\n * live stream. For non-active symbols, the host can push data via\r\n * `setEntry(symbol, …)` so the row reflects whatever the app already has.\r\n */\r\nexport interface WatchlistEntry {\r\n symbol: string;\r\n lastPrice?: number;\r\n /** Reference price for % calc (usually session open or 24h-ago close). */\r\n refPrice?: number;\r\n /** Recent close samples for the sparkline — last point is the live price. */\r\n sparkline?: number[];\r\n}\r\n\r\nexport interface WatchlistCallbacks {\r\n onSelect: (symbol: string) => void;\r\n}\r\n\r\nexport class WidgetWatchlist {\r\n private el: HTMLDivElement;\r\n private listEl: HTMLDivElement;\r\n private rowMap = new Map<string, {\r\n row: HTMLDivElement;\r\n priceEl: HTMLSpanElement;\r\n changeEl: HTMLSpanElement;\r\n sparkCanvas: HTMLCanvasElement;\r\n }>();\r\n private entries = new Map<string, WatchlistEntry>();\r\n private active: string | null = null;\r\n private callbacks: WatchlistCallbacks;\r\n private locale: string | undefined;\r\n\r\n constructor(host: HTMLElement, symbols: string[], callbacks: WatchlistCallbacks, title = 'Watchlist') {\r\n this.callbacks = callbacks;\r\n\r\n this.el = document.createElement('div');\r\n this.el.className = 'tcw-watchlist';\r\n\r\n const header = document.createElement('div');\r\n header.className = 'tcw-watchlist-header';\r\n header.textContent = title;\r\n this.el.appendChild(header);\r\n\r\n this.listEl = document.createElement('div');\r\n this.listEl.className = 'tcw-watchlist-list';\r\n this.el.appendChild(this.listEl);\r\n\r\n for (const symbol of symbols) {\r\n this.entries.set(symbol, { symbol });\r\n this.appendRow(symbol);\r\n }\r\n\r\n host.appendChild(this.el);\r\n }\r\n\r\n /** Set the BCP 47 locale used for price/percent formatting. */\r\n setLocale(locale: string | undefined): void {\r\n this.locale = locale;\r\n for (const symbol of this.entries.keys()) this.renderRow(symbol);\r\n }\r\n\r\n /** Replace the symbol set. Rows are diff'd so DOM churn is minimal. */\r\n setSymbols(symbols: string[]): void {\r\n const next = new Set(symbols);\r\n for (const sym of this.rowMap.keys()) {\r\n if (!next.has(sym)) this.removeRow(sym);\r\n }\r\n for (const sym of symbols) {\r\n if (!this.rowMap.has(sym)) {\r\n this.entries.set(sym, this.entries.get(sym) ?? { symbol: sym });\r\n this.appendRow(sym);\r\n }\r\n }\r\n }\r\n\r\n setActive(symbol: string): void {\r\n if (this.active === symbol) return;\r\n if (this.active && this.rowMap.has(this.active)) {\r\n this.rowMap.get(this.active)!.row.classList.remove('tcw-watchlist-active');\r\n }\r\n this.active = symbol;\r\n const cur = this.rowMap.get(symbol);\r\n if (cur) cur.row.classList.add('tcw-watchlist-active');\r\n }\r\n\r\n /** Push a price tick into a row. The widget calls this automatically for\r\n * the active symbol. Apps can call it for the rest. */\r\n setEntry(symbol: string, patch: Partial<WatchlistEntry>): void {\r\n const prev = this.entries.get(symbol) ?? { symbol };\r\n const next = { ...prev, ...patch };\r\n this.entries.set(symbol, next);\r\n this.renderRow(symbol);\r\n }\r\n\r\n destroy(): void {\r\n this.el.remove();\r\n this.rowMap.clear();\r\n this.entries.clear();\r\n }\r\n\r\n private appendRow(symbol: string): void {\r\n const row = document.createElement('div');\r\n row.className = 'tcw-watchlist-row';\r\n row.tabIndex = 0;\r\n\r\n const label = document.createElement('div');\r\n label.className = 'tcw-watchlist-symbol';\r\n label.textContent = formatSymbol(symbol);\r\n\r\n const spark = document.createElement('canvas');\r\n spark.className = 'tcw-watchlist-spark';\r\n spark.width = 64;\r\n spark.height = 22;\r\n\r\n const right = document.createElement('div');\r\n right.className = 'tcw-watchlist-stats';\r\n const priceEl = document.createElement('span');\r\n priceEl.className = 'tcw-watchlist-price';\r\n priceEl.textContent = '—';\r\n const changeEl = document.createElement('span');\r\n changeEl.className = 'tcw-watchlist-change';\r\n changeEl.textContent = '';\r\n right.appendChild(priceEl);\r\n right.appendChild(changeEl);\r\n\r\n row.appendChild(label);\r\n row.appendChild(spark);\r\n row.appendChild(right);\r\n\r\n row.addEventListener('click', () => this.callbacks.onSelect(symbol));\r\n row.addEventListener('keydown', (e) => {\r\n if (e.key === 'Enter' || e.key === ' ') {\r\n e.preventDefault();\r\n this.callbacks.onSelect(symbol);\r\n }\r\n });\r\n\r\n this.listEl.appendChild(row);\r\n this.rowMap.set(symbol, { row, priceEl, changeEl, sparkCanvas: spark });\r\n if (symbol === this.active) row.classList.add('tcw-watchlist-active');\r\n }\r\n\r\n private removeRow(symbol: string): void {\r\n const ref = this.rowMap.get(symbol);\r\n if (!ref) return;\r\n ref.row.remove();\r\n this.rowMap.delete(symbol);\r\n }\r\n\r\n private renderRow(symbol: string): void {\r\n const ref = this.rowMap.get(symbol);\r\n const entry = this.entries.get(symbol);\r\n if (!ref || !entry) return;\r\n\r\n if (entry.lastPrice !== undefined) {\r\n ref.priceEl.textContent = formatPrice(entry.lastPrice, this.locale);\r\n }\r\n\r\n if (entry.lastPrice !== undefined && entry.refPrice !== undefined && entry.refPrice !== 0) {\r\n const diff = entry.lastPrice - entry.refPrice;\r\n const pct = (diff / entry.refPrice) * 100;\r\n const sign = diff >= 0 ? '+' : '-';\r\n const pctText = Math.abs(pct).toLocaleString(this.locale, { minimumFractionDigits: 2, maximumFractionDigits: 2 });\r\n ref.changeEl.textContent = `${sign}${pctText}%`;\r\n ref.changeEl.className = `tcw-watchlist-change ${diff >= 0 ? 'tcw-up' : 'tcw-down'}`;\r\n } else {\r\n ref.changeEl.textContent = '';\r\n }\r\n\r\n if (entry.sparkline && entry.sparkline.length >= 2) {\r\n drawSparkline(ref.sparkCanvas, entry.sparkline, entry.refPrice ?? entry.sparkline[0]);\r\n }\r\n }\r\n}\r\n\r\nfunction formatSymbol(symbol: string): string {\r\n // Add a / separator for typical crypto pair suffixes; leaves stock tickers\r\n // (AAPL, NVDA) alone.\r\n for (const quote of ['USDT', 'USD', 'BTC', 'ETH', 'EUR']) {\r\n if (symbol.length > quote.length && symbol.endsWith(quote)) {\r\n return symbol.slice(0, -quote.length) + '/' + quote;\r\n }\r\n }\r\n return symbol;\r\n}\r\n\r\nfunction formatPrice(v: number, locale: string | undefined): string {\r\n if (v === 0) return '0';\r\n const abs = Math.abs(v);\r\n if (abs >= 1000) return v.toLocaleString(locale, { minimumFractionDigits: 2, maximumFractionDigits: 2 });\r\n if (abs >= 1) return v.toLocaleString(locale, { minimumFractionDigits: 4, maximumFractionDigits: 4 });\r\n // toPrecision(4) has no locale-aware equivalent via toLocaleString (it\r\n // targets significant digits, not decimal places) — reformat its raw\r\n // fixed-notation output through Number.toLocaleString for the separator.\r\n const precise = Number(v.toPrecision(4));\r\n return precise.toLocaleString(locale, { maximumFractionDigits: 10 });\r\n}\r\n\r\nfunction drawSparkline(canvas: HTMLCanvasElement, samples: number[], ref: number): void {\r\n const ctx = canvas.getContext('2d');\r\n if (!ctx) return;\r\n const dpr = window.devicePixelRatio || 1;\r\n if (canvas.width !== canvas.clientWidth * dpr) {\r\n canvas.width = (canvas.clientWidth || 64) * dpr;\r\n canvas.height = (canvas.clientHeight || 22) * dpr;\r\n }\r\n const w = canvas.width;\r\n const h = canvas.height;\r\n\r\n let lo = Infinity, hi = -Infinity;\r\n for (const v of samples) {\r\n if (v < lo) lo = v;\r\n if (v > hi) hi = v;\r\n }\r\n const span = Math.max(hi - lo, 1e-9);\r\n const last = samples[samples.length - 1];\r\n const up = last >= ref;\r\n const color = up ? '#1fa874' : '#e8505b';\r\n\r\n ctx.clearRect(0, 0, w, h);\r\n ctx.lineWidth = 1.4 * dpr;\r\n ctx.strokeStyle = color;\r\n ctx.beginPath();\r\n const step = w / (samples.length - 1);\r\n for (let i = 0; i < samples.length; i++) {\r\n const x = i * step;\r\n const y = h - ((samples[i] - lo) / span) * (h - 4) - 2;\r\n if (i === 0) ctx.moveTo(x, y); else ctx.lineTo(x, y);\r\n }\r\n ctx.stroke();\r\n}\r\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';\r\n\r\nexport interface ObjectTreeIndicator {\r\n instanceId: string;\r\n name: string;\r\n visible: boolean;\r\n}\r\n\r\nexport interface ObjectTreeDrawing {\r\n id: string;\r\n label: string;\r\n visible: boolean;\r\n locked: boolean;\r\n}\r\n\r\nexport interface ObjectTreeCompare {\r\n id: string;\r\n label: string;\r\n color: string;\r\n}\r\n\r\nexport interface ObjectTreeCallbacks {\r\n onRemoveIndicator: (instanceId: string) => void;\r\n onConfigureIndicator?: (instanceId: string) => void;\r\n onToggleIndicatorVisible?: (instanceId: string, visible: boolean) => void;\r\n onRemoveDrawing: (id: string) => void;\r\n onToggleDrawingVisible: (id: string, visible: boolean) => void;\r\n onToggleDrawingLocked: (id: string, locked: boolean) => void;\r\n /** When provided, a Compare section with an \"add\" button is shown. */\r\n onAddCompare?: () => void;\r\n onRemoveCompare?: (id: string) => void;\r\n}\r\n\r\n/**\r\n * Object-tree panel — a layers manager. Lists every active\r\n * indicator and drawing on the chart with per-item controls: indicators can be\r\n * removed; drawings can be shown/hidden, locked/unlocked, and removed. Toggled\r\n * from the toolbar layers button; the host wires actions back to the chart.\r\n */\r\nexport class WidgetObjectTree {\r\n private el: HTMLDivElement;\r\n private indicatorsEl: HTMLDivElement;\r\n private drawingsEl: HTMLDivElement;\r\n private compareEl: HTMLDivElement | null = null;\r\n private callbacks: ObjectTreeCallbacks;\r\n private open = false;\r\n\r\n constructor(host: HTMLElement, callbacks: ObjectTreeCallbacks) {\r\n this.callbacks = callbacks;\r\n\r\n this.el = document.createElement('div');\r\n this.el.className = 'tcw-tree-panel';\r\n this.el.hidden = true;\r\n\r\n const header = document.createElement('div');\r\n header.className = 'tcw-tree-header';\r\n const title = document.createElement('span');\r\n title.textContent = 'Objects';\r\n const closeBtn = document.createElement('button');\r\n closeBtn.type = 'button';\r\n closeBtn.className = 'tcw-tree-close';\r\n closeBtn.setAttribute('aria-label', 'Close objects');\r\n closeBtn.innerHTML = createIcon('x', 14);\r\n closeBtn.addEventListener('click', () => this.close());\r\n header.appendChild(title);\r\n header.appendChild(closeBtn);\r\n this.el.appendChild(header);\r\n\r\n this.indicatorsEl = this.makeSection('Indicators');\r\n this.drawingsEl = this.makeSection('Drawings');\r\n if (this.callbacks.onAddCompare) {\r\n this.compareEl = this.makeSection('Compare', () => this.callbacks.onAddCompare?.());\r\n }\r\n\r\n host.appendChild(this.el);\r\n }\r\n\r\n isOpen(): boolean {\r\n return this.open;\r\n }\r\n\r\n toggle(): void {\r\n this.open ? this.close() : this.openPanel();\r\n }\r\n\r\n openPanel(): void {\r\n this.open = true;\r\n this.el.hidden = false;\r\n }\r\n\r\n close(): void {\r\n this.open = false;\r\n this.el.hidden = true;\r\n }\r\n\r\n destroy(): void {\r\n this.el.remove();\r\n }\r\n\r\n /** Replace all lists. Cheap full re-render — counts are small. */\r\n setObjects(\r\n indicators: ObjectTreeIndicator[],\r\n drawings: ObjectTreeDrawing[],\r\n compares: ObjectTreeCompare[] = [],\r\n ): void {\r\n this.renderIndicators(indicators);\r\n this.renderDrawings(drawings);\r\n this.renderCompares(compares);\r\n }\r\n\r\n private makeSection(title: string, onAdd?: () => void): HTMLDivElement {\r\n const wrap = document.createElement('div');\r\n wrap.className = 'tcw-tree-section';\r\n const head = document.createElement('div');\r\n head.className = 'tcw-tree-section-head';\r\n const label = document.createElement('span');\r\n label.textContent = title;\r\n head.appendChild(label);\r\n if (onAdd) {\r\n const addBtn = document.createElement('button');\r\n addBtn.type = 'button';\r\n addBtn.className = 'tcw-tree-add';\r\n addBtn.setAttribute('aria-label', `Add ${title.toLowerCase()}`);\r\n addBtn.title = `Add ${title.toLowerCase()}`;\r\n addBtn.innerHTML = createIcon('plus', 13);\r\n addBtn.addEventListener('click', onAdd);\r\n head.appendChild(addBtn);\r\n }\r\n const list = document.createElement('div');\r\n list.className = 'tcw-tree-list';\r\n wrap.appendChild(head);\r\n wrap.appendChild(list);\r\n this.el.appendChild(wrap);\r\n return list;\r\n }\r\n\r\n private renderIndicators(indicators: ObjectTreeIndicator[]): void {\r\n this.indicatorsEl.replaceChildren();\r\n if (indicators.length === 0) {\r\n this.indicatorsEl.appendChild(this.emptyRow('No indicators'));\r\n return;\r\n }\r\n for (const ind of indicators) {\r\n const row = this.row(ind.name);\r\n if (!ind.visible) row.classList.add('tcw-tree-hidden');\r\n const actions = document.createElement('div');\r\n actions.className = 'tcw-tree-actions';\r\n if (this.callbacks.onToggleIndicatorVisible) {\r\n actions.appendChild(this.iconButton(\r\n ind.visible ? 'eye' : 'eyeOff',\r\n ind.visible ? 'Hide' : 'Show',\r\n '',\r\n () => this.callbacks.onToggleIndicatorVisible?.(ind.instanceId, !ind.visible),\r\n ));\r\n }\r\n if (this.callbacks.onConfigureIndicator) {\r\n actions.appendChild(this.iconButton('settings', 'Indicator settings', '', () =>\r\n this.callbacks.onConfigureIndicator?.(ind.instanceId),\r\n ));\r\n }\r\n actions.appendChild(this.iconButton('trash', 'Remove indicator', 'tcw-tree-del', () =>\r\n this.callbacks.onRemoveIndicator(ind.instanceId),\r\n ));\r\n row.appendChild(actions);\r\n this.indicatorsEl.appendChild(row);\r\n }\r\n }\r\n\r\n private renderDrawings(drawings: ObjectTreeDrawing[]): void {\r\n this.drawingsEl.replaceChildren();\r\n if (drawings.length === 0) {\r\n this.drawingsEl.appendChild(this.emptyRow('No drawings'));\r\n return;\r\n }\r\n for (const d of drawings) {\r\n const row = this.row(d.label);\r\n if (!d.visible) row.classList.add('tcw-tree-hidden');\r\n\r\n const actions = document.createElement('div');\r\n actions.className = 'tcw-tree-actions';\r\n actions.appendChild(this.iconButton(\r\n d.visible ? 'eye' : 'eyeOff',\r\n d.visible ? 'Hide' : 'Show',\r\n '',\r\n () => this.callbacks.onToggleDrawingVisible(d.id, !d.visible),\r\n ));\r\n actions.appendChild(this.iconButton(\r\n d.locked ? 'lock' : 'unlock',\r\n d.locked ? 'Unlock' : 'Lock',\r\n d.locked ? 'tcw-tree-on' : '',\r\n () => this.callbacks.onToggleDrawingLocked(d.id, !d.locked),\r\n ));\r\n actions.appendChild(this.iconButton('trash', 'Remove drawing', 'tcw-tree-del', () =>\r\n this.callbacks.onRemoveDrawing(d.id),\r\n ));\r\n row.appendChild(actions);\r\n this.drawingsEl.appendChild(row);\r\n }\r\n }\r\n\r\n private renderCompares(compares: ObjectTreeCompare[]): void {\r\n if (!this.compareEl) return;\r\n this.compareEl.replaceChildren();\r\n if (compares.length === 0) {\r\n this.compareEl.appendChild(this.emptyRow('No comparisons'));\r\n return;\r\n }\r\n for (const c of compares) {\r\n const row = this.row(c.label);\r\n const dot = document.createElement('span');\r\n dot.className = 'tcw-tree-dot';\r\n dot.style.background = c.color;\r\n row.insertBefore(dot, row.firstChild);\r\n if (this.callbacks.onRemoveCompare) {\r\n row.appendChild(this.iconButton('trash', 'Remove comparison', 'tcw-tree-del', () =>\r\n this.callbacks.onRemoveCompare?.(c.id),\r\n ));\r\n }\r\n this.compareEl.appendChild(row);\r\n }\r\n }\r\n\r\n private row(label: string): HTMLDivElement {\r\n const row = document.createElement('div');\r\n row.className = 'tcw-tree-row';\r\n const name = document.createElement('span');\r\n name.className = 'tcw-tree-name';\r\n name.textContent = label;\r\n name.title = label;\r\n row.appendChild(name);\r\n return row;\r\n }\r\n\r\n private emptyRow(text: string): HTMLDivElement {\r\n const el = document.createElement('div');\r\n el.className = 'tcw-tree-empty';\r\n el.textContent = text;\r\n return el;\r\n }\r\n\r\n private iconButton(icon: string, label: string, extraClass: string, onClick: () => void): HTMLButtonElement {\r\n const btn = document.createElement('button');\r\n btn.type = 'button';\r\n btn.className = `tcw-tree-btn ${extraClass}`.trim();\r\n btn.setAttribute('aria-label', label);\r\n btn.title = label;\r\n btn.innerHTML = createIcon(icon, 14);\r\n btn.addEventListener('click', onClick);\r\n return btn;\r\n }\r\n}\r\n\r\nconst DRAWING_TYPE_LABELS: Record<string, string> = {\r\n trendLine: 'Trend Line',\r\n ray: 'Ray',\r\n extendedLine: 'Extended Line',\r\n horizontalLine: 'Horizontal Line',\r\n horizontalRay: 'Horizontal Ray',\r\n crossLine: 'Cross Line',\r\n infoLine: 'Info Line',\r\n trendAngle: 'Trend Angle',\r\n circle: 'Circle',\r\n fibChannel: 'Fib Channel',\r\n fibSpeedResistanceFan: 'Fib Speed Resistance Fan',\r\n schiffPitchfork: 'Schiff Pitchfork',\r\n modifiedSchiffPitchfork: 'Modified Schiff Pitchfork',\r\n xabcdPattern: 'XABCD Pattern',\r\n abcdPattern: 'ABCD Pattern',\r\n headAndShoulders: 'Head and Shoulders',\r\n dateAndPriceRange: 'Date and Price Range',\r\n cyclicLines: 'Cyclic Lines',\r\n priceLabel: 'Price Label',\r\n verticalLine: 'Vertical Line',\r\n rectangle: 'Rectangle',\r\n ellipse: 'Ellipse',\r\n triangle: 'Triangle',\r\n arrow: 'Arrow',\r\n parallelChannel: 'Parallel Channel',\r\n regressionChannel: 'Regression Channel',\r\n pitchfork: 'Pitchfork',\r\n fibRetracement: 'Fib Retracement',\r\n fibExtension: 'Fib Extension',\r\n fibTimeZones: 'Fib Time Zones',\r\n gannBox: 'Gann Box',\r\n gannFan: 'Gann Fan',\r\n elliottWave: 'Elliott Wave',\r\n priceRange: 'Price Range',\r\n dateRange: 'Date Range',\r\n measure: 'Measure',\r\n text: 'Text',\r\n textAnnotation: 'Text',\r\n anchoredVWAP: 'Anchored VWAP',\r\n volumeProfileRange: 'Volume Profile',\r\n riskReward: 'Long/Short Position',\r\n};\r\n\r\n/** Human-readable label for a drawing type, falling back to the raw key. */\r\nexport function drawingTypeLabel(type: string): string {\r\n return DRAWING_TYPE_LABELS[type] ?? type;\r\n}\r\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';\r\nimport { createIcon } from './icons.js';\r\nimport { DrawingTemplateStore } from './DrawingTemplateStore.js';\r\n\r\nexport interface DrawingStyleCallbacks {\r\n /** Apply a style change to the active (next) drawing and the selected one. */\r\n onStyleChange: (style: Partial<DrawingStyle>) => void;\r\n /** Current active drawing style, for seeding controls and saving templates. */\r\n getStyle: () => DrawingStyle;\r\n}\r\n\r\nconst SWATCHES = ['#4c8dff', '#1fa874', '#e8505b', '#f2a93b', '#a57cff', '#1398a8', '#ffffff', '#7d8696'];\r\nconst WIDTHS = [1, 2, 3, 4];\r\nconst LINE_STYLES: DrawingStyle['lineStyle'][] = ['solid', 'dashed', 'dotted'];\r\n\r\n/**\r\n * Drawing style popover — pick colour, line width, and line style for the next\r\n * drawing (and the selected one), plus save/apply named style templates\r\n * persisted via `DrawingTemplateStore`.\r\n */\r\nexport class WidgetDrawingStyle {\r\n private el: HTMLDivElement;\r\n private templatesEl: HTMLDivElement;\r\n private nameInput: HTMLInputElement;\r\n private callbacks: DrawingStyleCallbacks;\r\n private store: DrawingTemplateStore;\r\n private open = false;\r\n\r\n constructor(host: HTMLElement, callbacks: DrawingStyleCallbacks, store: DrawingTemplateStore) {\r\n this.callbacks = callbacks;\r\n this.store = store;\r\n\r\n this.el = document.createElement('div');\r\n this.el.className = 'tcw-style-panel';\r\n this.el.hidden = true;\r\n\r\n const header = document.createElement('div');\r\n header.className = 'tcw-style-header';\r\n const title = document.createElement('span');\r\n title.textContent = 'Drawing Style';\r\n const closeBtn = document.createElement('button');\r\n closeBtn.type = 'button';\r\n closeBtn.className = 'tcw-style-close';\r\n closeBtn.setAttribute('aria-label', 'Close');\r\n closeBtn.innerHTML = createIcon('x', 14);\r\n closeBtn.addEventListener('click', () => this.close());\r\n header.appendChild(title);\r\n header.appendChild(closeBtn);\r\n this.el.appendChild(header);\r\n\r\n this.el.appendChild(this.colorRow());\r\n this.el.appendChild(this.widthRow());\r\n this.el.appendChild(this.lineStyleRow());\r\n\r\n // Templates\r\n const tmplHead = document.createElement('div');\r\n tmplHead.className = 'tcw-style-subhead';\r\n tmplHead.textContent = 'Templates';\r\n this.el.appendChild(tmplHead);\r\n\r\n const saveRow = document.createElement('div');\r\n saveRow.className = 'tcw-style-save';\r\n this.nameInput = document.createElement('input');\r\n this.nameInput.type = 'text';\r\n this.nameInput.placeholder = 'Template name';\r\n this.nameInput.className = 'tcw-style-name';\r\n const saveBtn = document.createElement('button');\r\n saveBtn.type = 'button';\r\n saveBtn.className = 'tcw-style-savebtn';\r\n saveBtn.innerHTML = `${createIcon('plus', 13)}<span>Save</span>`;\r\n saveBtn.addEventListener('click', () => this.saveTemplate());\r\n saveRow.appendChild(this.nameInput);\r\n saveRow.appendChild(saveBtn);\r\n this.el.appendChild(saveRow);\r\n\r\n this.templatesEl = document.createElement('div');\r\n this.templatesEl.className = 'tcw-style-templates';\r\n this.el.appendChild(this.templatesEl);\r\n\r\n host.appendChild(this.el);\r\n this.renderTemplates();\r\n }\r\n\r\n isOpen(): boolean {\r\n return this.open;\r\n }\r\n\r\n toggle(): void {\r\n this.open ? this.close() : this.openPanel();\r\n }\r\n\r\n openPanel(): void {\r\n this.open = true;\r\n this.el.hidden = false;\r\n this.syncActiveControls();\r\n this.renderTemplates();\r\n }\r\n\r\n close(): void {\r\n this.open = false;\r\n this.el.hidden = true;\r\n }\r\n\r\n destroy(): void {\r\n this.el.remove();\r\n }\r\n\r\n private colorRow(): HTMLDivElement {\r\n const row = document.createElement('div');\r\n row.className = 'tcw-style-row tcw-style-colors';\r\n for (const c of SWATCHES) {\r\n const sw = document.createElement('button');\r\n sw.type = 'button';\r\n sw.className = 'tcw-style-swatch';\r\n sw.style.background = c;\r\n sw.dataset.color = c;\r\n sw.setAttribute('aria-label', c);\r\n sw.addEventListener('click', () => this.applyStyle({ color: c }));\r\n row.appendChild(sw);\r\n }\r\n const picker = document.createElement('input');\r\n picker.type = 'color';\r\n picker.className = 'tcw-style-picker';\r\n picker.addEventListener('input', () => this.applyStyle({ color: picker.value }));\r\n row.appendChild(picker);\r\n return row;\r\n }\r\n\r\n private widthRow(): HTMLDivElement {\r\n const row = document.createElement('div');\r\n row.className = 'tcw-style-row tcw-style-widths';\r\n for (const w of WIDTHS) {\r\n const btn = document.createElement('button');\r\n btn.type = 'button';\r\n btn.className = 'tcw-style-width';\r\n btn.dataset.width = String(w);\r\n const bar = document.createElement('span');\r\n bar.style.height = `${w}px`;\r\n btn.appendChild(bar);\r\n btn.addEventListener('click', () => this.applyStyle({ lineWidth: w }));\r\n row.appendChild(btn);\r\n }\r\n return row;\r\n }\r\n\r\n private lineStyleRow(): HTMLDivElement {\r\n const row = document.createElement('div');\r\n row.className = 'tcw-style-row tcw-style-dashes';\r\n for (const ls of LINE_STYLES) {\r\n const btn = document.createElement('button');\r\n btn.type = 'button';\r\n btn.className = 'tcw-style-dash';\r\n btn.dataset.linestyle = ls;\r\n btn.textContent = ls === 'solid' ? '──' : ls === 'dashed' ? '╌╌' : '┄┄';\r\n btn.title = ls;\r\n btn.addEventListener('click', () => this.applyStyle({ lineStyle: ls }));\r\n row.appendChild(btn);\r\n }\r\n return row;\r\n }\r\n\r\n private applyStyle(patch: Partial<DrawingStyle>): void {\r\n this.callbacks.onStyleChange(patch);\r\n this.syncActiveControls();\r\n }\r\n\r\n /** Mark the controls matching the current active style. */\r\n private syncActiveControls(): void {\r\n const style = this.callbacks.getStyle();\r\n this.el.querySelectorAll<HTMLElement>('.tcw-style-swatch').forEach((sw) => {\r\n sw.classList.toggle('tcw-on', sw.dataset.color?.toLowerCase() === style.color?.toLowerCase());\r\n });\r\n this.el.querySelectorAll<HTMLElement>('.tcw-style-width').forEach((b) => {\r\n b.classList.toggle('tcw-on', Number(b.dataset.width) === style.lineWidth);\r\n });\r\n this.el.querySelectorAll<HTMLElement>('.tcw-style-dash').forEach((b) => {\r\n b.classList.toggle('tcw-on', b.dataset.linestyle === style.lineStyle);\r\n });\r\n }\r\n\r\n private saveTemplate(): void {\r\n const name = this.nameInput.value.trim();\r\n if (!name) return;\r\n this.store.save(name, this.callbacks.getStyle());\r\n this.nameInput.value = '';\r\n this.renderTemplates();\r\n }\r\n\r\n private renderTemplates(): void {\r\n this.templatesEl.replaceChildren();\r\n const templates = this.store.list();\r\n if (templates.length === 0) {\r\n const empty = document.createElement('div');\r\n empty.className = 'tcw-style-empty';\r\n empty.textContent = 'No saved templates';\r\n this.templatesEl.appendChild(empty);\r\n return;\r\n }\r\n for (const t of templates) {\r\n const row = document.createElement('div');\r\n row.className = 'tcw-style-template';\r\n\r\n const apply = document.createElement('button');\r\n apply.type = 'button';\r\n apply.className = 'tcw-style-apply';\r\n const dot = document.createElement('span');\r\n dot.className = 'tcw-style-tdot';\r\n dot.style.background = (t.style.color as string) ?? 'var(--tcw-text-muted)';\r\n const label = document.createElement('span');\r\n label.textContent = t.name;\r\n apply.appendChild(dot);\r\n apply.appendChild(label);\r\n apply.addEventListener('click', () => {\r\n this.callbacks.onStyleChange({ ...t.style });\r\n this.syncActiveControls();\r\n });\r\n\r\n const del = document.createElement('button');\r\n del.type = 'button';\r\n del.className = 'tcw-style-tdel';\r\n del.setAttribute('aria-label', 'Delete template');\r\n del.innerHTML = createIcon('trash', 13);\r\n del.addEventListener('click', () => {\r\n this.store.remove(t.name);\r\n this.renderTemplates();\r\n });\r\n\r\n row.appendChild(apply);\r\n row.appendChild(del);\r\n this.templatesEl.appendChild(row);\r\n }\r\n }\r\n}\r\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 type { TimeFrame } from '@tradecanvas/commons';\nimport { timeframeToMs } from '@tradecanvas/commons';\n\n/** The timeframe menu when the host offers no list of its own. */\nexport const WIDGET_TIMEFRAMES: TimeFrame[] = ['1m', '3m', '5m', '15m', '30m', '1h', '2h', '4h', '1d', '1w', '1M'];\n\n/** On the toolbar until the user pins others. */\nexport const WIDGET_TIMEFRAME_FAVORITES: TimeFrame[] = ['1m', '5m', '15m', '1h', '4h', '1d'];\n\nconst MAX_FALLBACK_FAVORITES = 6;\n\n/** \"1m\", \"1H\", \"1D\", \"1W\"; minutes and months keep their case (\"1m\" vs \"1M\"). */\nexport function timeframeLabel(tf: TimeFrame): string {\n const unit = tf.slice(-1);\n return unit === 'h' || unit === 'd' || unit === 'w' ? tf.slice(0, -1) + unit.toUpperCase() : tf;\n}\n\nconst isKnown = (tf: TimeFrame): boolean => Number.isFinite(timeframeToMs(tf));\n\n/**\n * The timeframes to offer, shortest first: the widget's own list (or the\n * default menu), less any that the chart's `features.timeframes` whitelist\n * leaves out.\n */\nexport function availableTimeframes(widgetList?: TimeFrame[], whitelist?: TimeFrame[]): TimeFrame[] {\n const allowed = whitelist?.length ? whitelist : null;\n const base = widgetList?.length ? widgetList : (allowed ?? WIDGET_TIMEFRAMES);\n return [...new Set(base)]\n .filter((tf) => isKnown(tf) && (!allowed || allowed.includes(tf)))\n .sort((a, b) => timeframeToMs(a) - timeframeToMs(b));\n}\n\n/**\n * The toolbar's first favourites: the host's defaults; else, when the host\n * chose the list, all of it (so a short custom list shows as before); else\n * the standard set; else the first few offered.\n */\nexport function initialTimeframeFavorites(\n available: TimeFrame[],\n hostDefaults?: TimeFrame[],\n hostChoseList = false,\n): TimeFrame[] {\n if (hostDefaults?.length) return available.filter((tf) => hostDefaults.includes(tf));\n if (hostChoseList) return [...available];\n const standard = available.filter((tf) => WIDGET_TIMEFRAME_FAVORITES.includes(tf));\n return standard.length > 0 ? standard : available.slice(0, MAX_FALLBACK_FAVORITES);\n}\n","const MINUTE_MS = 60_000;\nconst DATE_RE = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\nconst TIME_RE = /^(\\d{2}):(\\d{2})$/;\n\n/**\n * A wall-clock date (\"2026-03-01\") and time (\"14:30\", empty = midnight) in the\n * display timezone (`tzOffsetMinutes` east of UTC; null = the browser's) as a\n * UTC timestamp. Null when the date or time is not valid.\n */\nexport function wallTimeToUtc(date: string, time: string, tzOffsetMinutes: number | null): number | null {\n const d = DATE_RE.exec(date);\n const t = time ? TIME_RE.exec(time) : ['', '00', '00'];\n if (!d || !t) return null;\n const [year, month, day, hours, minutes] = [+d[1], +d[2], +d[3], +t[1], +t[2]];\n if (month < 1 || month > 12 || day < 1 || day > 31 || hours > 23 || minutes > 59) return null;\n if (tzOffsetMinutes === null) {\n const local = new Date(year, month - 1, day, hours, minutes);\n return local.getDate() === day ? local.getTime() : null; // 31 February rolls over: reject\n }\n const utc = Date.UTC(year, month - 1, day, hours, minutes);\n if (new Date(utc).getUTCDate() !== day) return null;\n return utc - tzOffsetMinutes * MINUTE_MS;\n}\n\n/** The date and time fields' values for `ts` in the display timezone. */\nexport function utcToWallTime(ts: number, tzOffsetMinutes: number | null): { date: string; time: string } {\n const pad = (n: number) => String(n).padStart(2, '0');\n if (tzOffsetMinutes === null) {\n const d = new Date(ts);\n return {\n date: `${d.getFullYear()}-${pad(d.getMonth() + 1)}-${pad(d.getDate())}`,\n time: `${pad(d.getHours())}:${pad(d.getMinutes())}`,\n };\n }\n const d = new Date(ts + tzOffsetMinutes * MINUTE_MS);\n return {\n date: `${d.getUTCFullYear()}-${pad(d.getUTCMonth() + 1)}-${pad(d.getUTCDate())}`,\n time: `${pad(d.getUTCHours())}:${pad(d.getUTCMinutes())}`,\n };\n}\n\nexport interface GoToDateLabels {\n title: string;\n date: string;\n time: string;\n submit: string;\n cancel: string;\n}\n\n/**\n * \"Go to date\" popover: a date and an optional time. Enter submits, Escape or\n * a click outside closes it, and focus returns to whatever opened it.\n */\nexport class WidgetGoToDate {\n private form: HTMLFormElement | null = null;\n private returnFocus: HTMLElement | null = null;\n /** The button that opened it: pressing it again toggles, so it's not \"outside\". */\n private opener: Element | null = null;\n private readonly onOutside = (e: MouseEvent) => {\n const target = e.target as Node;\n if (this.form && !this.form.contains(target) && !this.opener?.contains(target)) this.close();\n };\n\n constructor(\n private readonly host: HTMLElement,\n private readonly labels: GoToDateLabels,\n private readonly onSubmit: (value: { date: string; time: string }) => void,\n ) {}\n\n isOpen(): boolean {\n return this.form !== null;\n }\n\n open(initial: { date: string; time: string }, opener: Element | null = null): void {\n this.close();\n this.opener = opener;\n this.returnFocus = document.activeElement as HTMLElement | null;\n\n const form = document.createElement('form');\n form.className = 'tcw-goto';\n form.setAttribute('role', 'dialog');\n form.setAttribute('aria-label', this.labels.title);\n\n const title = document.createElement('div');\n title.className = 'tcw-goto-title';\n title.textContent = this.labels.title;\n\n const date = this.field(form, this.labels.date, 'date', initial.date);\n date.required = true;\n const time = this.field(form, this.labels.time, 'time', initial.time);\n\n const actions = document.createElement('div');\n actions.className = 'tcw-goto-actions';\n const cancel = document.createElement('button');\n cancel.type = 'button';\n cancel.className = 'tcw-btn';\n cancel.textContent = this.labels.cancel;\n cancel.addEventListener('click', () => this.close());\n const submit = document.createElement('button');\n submit.type = 'submit';\n submit.className = 'tcw-btn tcw-goto-submit';\n submit.textContent = this.labels.submit;\n actions.append(cancel, submit);\n\n form.prepend(title);\n form.append(actions);\n form.addEventListener('submit', (e) => {\n e.preventDefault();\n if (!date.value) return;\n const value = { date: date.value, time: time.value };\n this.close();\n this.onSubmit(value);\n });\n form.addEventListener('keydown', (e) => {\n e.stopPropagation(); // typing here must not drive chart shortcuts\n if (e.key === 'Escape') this.close();\n });\n\n this.host.appendChild(form);\n this.form = form;\n document.addEventListener('mousedown', this.onOutside);\n date.focus();\n }\n\n close(): void {\n if (!this.form) return;\n document.removeEventListener('mousedown', this.onOutside);\n this.form.remove();\n this.form = null;\n const back = this.returnFocus;\n this.returnFocus = null;\n if (back?.isConnected) back.focus();\n }\n\n destroy(): void {\n this.close();\n }\n\n private field(form: HTMLFormElement, label: string, type: 'date' | 'time', value: string): HTMLInputElement {\n const wrap = document.createElement('label');\n wrap.className = 'tcw-goto-field';\n const text = document.createElement('span');\n text.textContent = label;\n const input = document.createElement('input');\n input.type = type;\n input.value = value;\n input.className = 'tcw-goto-input';\n wrap.append(text, input);\n form.appendChild(wrap);\n return input;\n }\n}\n","/** Pause before the first tooltip shows. */\nexport const TOOLTIP_DELAY_MS = 300;\n/** After one hides, the next shows at once within this window (moving along a toolbar). */\nexport const TOOLTIP_WARM_MS = 500;\nconst GAP_PX = 8;\nconst EDGE_PX = 4;\nconst SLIDE_PX = 3;\n\ntype Side = 'top' | 'bottom' | 'left' | 'right';\nconst TIPPED = '[title]:not([title=\"\"]), [data-tip]:not([data-tip=\"\"])';\n\n/**\n * Quick, styled tooltips for the widget's controls, in place of the\n * browser's `title` tooltip (a fixed ~1 s wait, unstyled). Any element in\n * the widget with a `title` gets one. While the pointer is on it, its title\n * is lifted into `data-tip` so the browser's own tooltip can't appear, and\n * put back when the pointer leaves — so the title keeps doing its other jobs\n * (accessible description, selectors). Keyboard focus shows the tooltip too,\n * leaving the title in place. `data-tip-side` picks a side.\n */\nexport class WidgetTooltip {\n private readonly el: HTMLDivElement;\n private target: HTMLElement | null = null;\n private source: 'pointer' | 'focus' | null = null;\n /** The control just pressed (or keyed): no tooltip on it until the pointer leaves. */\n private pressed: HTMLElement | null = null;\n private showTimer: ReturnType<typeof setTimeout> | null = null;\n private watchFrame = 0;\n private warmUntil = 0;\n private readonly observer: MutationObserver;\n\n constructor(private readonly root: HTMLElement) {\n this.el = document.createElement('div');\n this.el.className = 'tcw-tooltip';\n this.el.setAttribute('aria-hidden', 'true'); // the control's title still describes it\n root.appendChild(this.el);\n\n root.addEventListener('pointerover', this.onOver);\n root.addEventListener('pointerout', this.onOut);\n root.addEventListener('pointerdown', this.onPress, true);\n root.addEventListener('keydown', this.onPress, true);\n root.addEventListener('focusin', this.onFocus);\n root.addEventListener('focusout', this.onBlur);\n root.addEventListener('wheel', this.hide, { passive: true });\n\n // Code that sets the title while the pointer is on the control (e.g.\n // \"Magnet ON\" ↔ \"Magnet OFF\" on click) mustn't bring the browser's back.\n this.observer = new MutationObserver(() => {\n // The control just clicked often renames itself (Hide → Show).\n if (this.pressed?.hasAttribute('title')) lift(this.pressed);\n const t = this.target;\n if (!t || this.source !== 'pointer' || !t.hasAttribute('title')) return;\n lift(t);\n if (this.isVisible()) this.show(t);\n });\n this.observer.observe(root, { subtree: true, attributes: true, attributeFilter: ['title'] });\n }\n\n destroy(): void {\n this.hide();\n if (this.pressed) restore(this.pressed);\n this.observer.disconnect();\n this.root.removeEventListener('pointerover', this.onOver);\n this.root.removeEventListener('pointerout', this.onOut);\n this.root.removeEventListener('pointerdown', this.onPress, true);\n this.root.removeEventListener('keydown', this.onPress, true);\n this.root.removeEventListener('focusin', this.onFocus);\n this.root.removeEventListener('focusout', this.onBlur);\n this.root.removeEventListener('wheel', this.hide);\n this.el.remove();\n }\n\n private readonly onOver = (e: PointerEvent): void => {\n if (e.pointerType === 'touch') return;\n const target = this.tipTarget(e.target);\n if (!target || target === this.pressed) return;\n if (target === this.target && this.source === 'pointer') return;\n lift(target);\n this.schedule(target, 'pointer', Date.now() < this.warmUntil || this.isVisible());\n };\n\n private readonly onOut = (e: PointerEvent): void => {\n const next = e.relatedTarget as Node | null;\n const within = (el: HTMLElement | null) => !!el && !!next && el.contains(next); // still on that control\n if (this.pressed && !within(this.pressed)) {\n restore(this.pressed);\n this.pressed = null;\n }\n if (this.source === 'pointer' && !within(this.target)) this.hide();\n };\n\n private readonly onPress = (): void => {\n const was = this.target;\n const lifted = this.source === 'pointer';\n this.warmUntil = 0;\n this.clearTimer();\n cancelAnimationFrame(this.watchFrame);\n this.el.classList.remove('tcw-tooltip--visible');\n this.target = null;\n this.source = null;\n // The title stays lifted while the pointer stays, or the browser's tooltip would take over.\n if (this.pressed && this.pressed !== was) restore(this.pressed);\n this.pressed = lifted ? was : null;\n };\n\n private readonly onFocus = (e: FocusEvent): void => {\n const target = this.tipTarget(e.target);\n // Keyboard focus only: a click focuses the control too, and that is no time for a tooltip.\n if (!target || !isFocusVisible(target) || target === this.pressed) return;\n this.schedule(target, 'focus', true);\n };\n\n private readonly onBlur = (e: FocusEvent): void => {\n if (this.source !== 'focus') return;\n const next = e.relatedTarget as Node | null;\n if (this.target && next && this.target.contains(next)) return;\n this.hide();\n };\n\n private readonly hide = (): void => {\n this.clearTimer();\n cancelAnimationFrame(this.watchFrame);\n if (this.isVisible()) this.warmUntil = Date.now() + TOOLTIP_WARM_MS;\n this.el.classList.remove('tcw-tooltip--visible');\n if (this.target && this.source === 'pointer') restore(this.target);\n this.target = null;\n this.source = null;\n };\n\n private tipTarget(node: EventTarget | null): HTMLElement | null {\n if (!(node instanceof Element)) return null;\n const el = node.closest<HTMLElement>(TIPPED);\n return el && el !== this.el && this.root.contains(el) ? el : null;\n }\n\n private schedule(target: HTMLElement, source: 'pointer' | 'focus', now: boolean): void {\n const previous = this.target;\n this.clearTimer();\n cancelAnimationFrame(this.watchFrame);\n if (previous && previous !== target && this.source === 'pointer') restore(previous);\n this.target = target;\n this.source = source;\n if (now) {\n this.show(target);\n return;\n }\n this.el.classList.remove('tcw-tooltip--visible');\n this.showTimer = setTimeout(() => {\n this.showTimer = null;\n if (this.target === target) this.show(target);\n }, TOOLTIP_DELAY_MS);\n }\n\n private show(target: HTMLElement): void {\n if (!isShown(target)) {\n this.hide();\n return;\n }\n this.el.textContent = tipText(target);\n this.place(target);\n this.el.classList.add('tcw-tooltip--visible');\n this.watch(target);\n }\n\n /** While shown, follow the control: gone, hidden or disabled takes the tooltip with it. */\n private watch(target: HTMLElement): void {\n cancelAnimationFrame(this.watchFrame);\n this.watchFrame = requestAnimationFrame(() => {\n if (this.target !== target) return;\n if (!isShown(target)) this.hide();\n else this.watch(target);\n });\n }\n\n /** Beside the control on its preferred side, flipped and clamped to stay inside the widget. */\n private place(target: HTMLElement): void {\n const box = this.root.getBoundingClientRect();\n const t = target.getBoundingClientRect();\n const w = this.el.offsetWidth;\n const h = this.el.offsetHeight;\n const left = t.left - box.left;\n const top = t.top - box.top;\n let side = preferredSide(target);\n if (side === 'bottom' && top + t.height + GAP_PX + h > box.height) side = 'top';\n else if (side === 'top' && top - GAP_PX - h < 0) side = 'bottom';\n else if (side === 'right' && left + t.width + GAP_PX + w > box.width) side = 'left';\n\n let x: number;\n let y: number;\n if (side === 'top' || side === 'bottom') {\n x = left + t.width / 2 - w / 2;\n y = side === 'bottom' ? top + t.height + GAP_PX : top - GAP_PX - h;\n } else {\n x = side === 'right' ? left + t.width + GAP_PX : left - GAP_PX - w;\n y = top + t.height / 2 - h / 2;\n }\n x = Math.max(EDGE_PX, Math.min(box.width - w - EDGE_PX, x));\n y = Math.max(EDGE_PX, Math.min(box.height - h - EDGE_PX, y));\n this.el.style.left = `${Math.round(x)}px`;\n this.el.style.top = `${Math.round(y)}px`;\n // It slides in from the control's side.\n const slide = { top: [0, SLIDE_PX], bottom: [0, -SLIDE_PX], left: [SLIDE_PX, 0], right: [-SLIDE_PX, 0] }[side];\n this.el.style.setProperty('--tcw-tip-dx', `${slide[0]}px`);\n this.el.style.setProperty('--tcw-tip-dy', `${slide[1]}px`);\n this.el.dataset.side = side;\n }\n\n private isVisible(): boolean {\n return this.el.classList.contains('tcw-tooltip--visible');\n }\n\n private clearTimer(): void {\n if (this.showTimer === null) return;\n clearTimeout(this.showTimer);\n this.showTimer = null;\n }\n}\n\n/** Take the title off while the pointer is on the control, keeping its text in `data-tip`. */\nfunction lift(el: HTMLElement): void {\n const title = el.getAttribute('title');\n if (title === null) return;\n el.dataset.tip = title;\n el.removeAttribute('title');\n}\n\n/** Put a lifted title back. */\nfunction restore(el: HTMLElement): void {\n if (el.dataset.tip !== undefined && !el.hasAttribute('title')) {\n el.setAttribute('title', el.dataset.tip);\n delete el.dataset.tip;\n }\n}\n\nfunction tipText(el: HTMLElement): string {\n return el.dataset.tip ?? el.getAttribute('title') ?? '';\n}\n\n/** Still on screen and usable: attached, laid out, not disabled. */\nfunction isShown(el: HTMLElement): boolean {\n return el.isConnected && el.getClientRects().length > 0 && !(el as HTMLButtonElement).disabled;\n}\n\nfunction isFocusVisible(el: HTMLElement): boolean {\n try {\n return el.matches(':focus-visible');\n } catch {\n return false; // engines without :focus-visible\n }\n}\n\nfunction preferredSide(el: HTMLElement): Side {\n const side = el.dataset.tipSide as Side | undefined;\n if (side) return side;\n if (el.closest('.tcw-sidebar')) return 'right';\n if (el.closest('.tcw-statusbar, .tcw-replay-bar')) return 'top';\n return 'bottom';\n}\n","import { createIcon } from './icons.js';\n\nexport interface IndicatorLegendRow {\n instanceId: string;\n /** \"EMA 50\", \"MACD 12 26 9\". */\n label: string;\n visible: boolean;\n /** The values at the bar in view; `color` null = the neutral text colour. */\n values: readonly { text: string; color: string | null }[];\n /**\n * Where the row sits inside its own pane (container px, `width` = the room\n * it may take); null = stacked under the OHLCV legend.\n */\n pane: { x: number; y: number; width: number } | null;\n}\n\nexport interface IndicatorLegendCallbacks {\n onToggleVisible: (instanceId: string, visible: boolean) => void;\n onSettings: (instanceId: string) => void;\n onRemove: (instanceId: string) => void;\n}\n\nexport interface IndicatorLegendLabels {\n show: string;\n hide: string;\n settings: string;\n remove: string;\n collapse: string;\n expand: string;\n}\n\n/** Collapsing is offered once this many indicators share the price pane. */\nconst COLLAPSE_FROM = 2;\n\ninterface RowEls {\n el: HTMLDivElement;\n name: HTMLButtonElement;\n values: HTMLSpanElement;\n eye: HTMLButtonElement;\n settings: HTMLButtonElement;\n remove: HTMLButtonElement;\n visible: boolean;\n valuesKey: string;\n state: string;\n placeKey: string;\n}\n\n/**\n * The indicators on the chart itself, instead of chips in the toolbar: price\n * pane indicators stack under the OHLCV legend, pane indicators sit at the\n * top of their pane. Each row reads \"EMA 50 123.45\" and, on hover or focus,\n * offers show/hide, settings and remove. A long stack can be collapsed.\n *\n * `update()` is cheap to call every frame: rows are kept by instance id and\n * only changed text and positions are written.\n */\nexport class WidgetIndicatorLegend {\n private readonly stack: HTMLDivElement;\n private readonly toggle: HTMLButtonElement;\n private readonly rows = new Map<string, RowEls>();\n private collapsed = false;\n private toggleKey = '';\n private stackKey = '';\n\n constructor(\n private readonly host: HTMLElement,\n private readonly callbacks: IndicatorLegendCallbacks,\n private readonly labels: IndicatorLegendLabels,\n ) {\n this.stack = document.createElement('div');\n this.stack.className = 'tcw-ind-legend';\n this.toggle = document.createElement('button');\n this.toggle.type = 'button';\n this.toggle.className = 'tcw-ind-legend-toggle';\n this.toggle.addEventListener('click', () => {\n this.setCollapsed(!this.collapsed);\n this.renderToggle(this.overlayCount());\n });\n this.stack.appendChild(this.toggle);\n host.appendChild(this.stack);\n }\n\n update(rows: readonly IndicatorLegendRow[], overlay: { left: number; top: number }): void {\n const stackKey = `${Math.round(overlay.left)},${Math.round(overlay.top)}`;\n if (stackKey !== this.stackKey) {\n this.stackKey = stackKey;\n this.stack.style.left = `${Math.round(overlay.left)}px`;\n this.stack.style.top = `${Math.round(overlay.top)}px`;\n }\n\n const seen = new Set<string>();\n let joinedStack = false;\n for (const row of rows) {\n seen.add(row.instanceId);\n const els = this.rows.get(row.instanceId) ?? this.createRow(row.instanceId);\n this.fill(els, row);\n if (row.pane) {\n if (els.el.parentElement !== this.host) this.host.appendChild(els.el);\n } else if (els.el.parentElement !== this.stack) {\n // New rows join the end (the chart's order), before the toggle.\n this.stack.insertBefore(els.el, this.toggle);\n joinedStack = true;\n }\n this.place(els, row.pane);\n }\n for (const [id, els] of this.rows) {\n if (seen.has(id)) continue;\n els.el.remove();\n this.rows.delete(id);\n }\n // A collapsed stack would hide the indicator just added: open it.\n if (joinedStack && this.collapsed) this.setCollapsed(false);\n this.renderToggle(rows.filter((r) => !r.pane).length);\n }\n\n destroy(): void {\n for (const els of this.rows.values()) els.el.remove();\n this.rows.clear();\n this.stack.remove();\n }\n\n private createRow(instanceId: string): RowEls {\n const el = document.createElement('div');\n el.className = 'tcw-ind-legend-row';\n el.dataset.instance = instanceId;\n\n const name = document.createElement('button');\n name.type = 'button';\n name.className = 'tcw-ind-legend-name';\n name.addEventListener('click', () => this.callbacks.onSettings(instanceId));\n\n const values = document.createElement('span');\n values.className = 'tcw-ind-legend-values';\n\n const actions = document.createElement('span');\n actions.className = 'tcw-ind-legend-actions';\n // Named in fill(), once the row's label is known.\n const action = (act: string, icon: string, run: () => void) => {\n const b = document.createElement('button');\n b.type = 'button';\n b.className = 'tcw-ind-legend-act';\n b.dataset.act = act;\n b.innerHTML = createIcon(icon, 13);\n b.addEventListener('click', run);\n actions.appendChild(b);\n return b;\n };\n const eye = action('visible', 'eye', () => {\n this.callbacks.onToggleVisible(instanceId, !els.visible);\n });\n const settings = action('settings', 'settings', () => this.callbacks.onSettings(instanceId));\n const remove = action('remove', 'x', () => this.callbacks.onRemove(instanceId));\n\n el.append(name, values, actions);\n const els: RowEls = {\n el, name, values, eye, settings, remove, visible: true, valuesKey: '', state: '', placeKey: '',\n };\n this.rows.set(instanceId, els);\n return els;\n }\n\n private fill(els: RowEls, row: IndicatorLegendRow): void {\n const state = `${row.label}|${row.visible}`;\n if (state !== els.state) {\n els.state = state;\n els.visible = row.visible;\n els.name.textContent = row.label;\n els.name.title = this.labels.settings;\n els.el.classList.toggle('tcw-ind-legend-row--hidden', !row.visible);\n els.eye.innerHTML = createIcon(row.visible ? 'eye' : 'eyeOff', 13);\n setLabel(els.eye, row.visible ? this.labels.hide : this.labels.show, row.label);\n setLabel(els.settings, this.labels.settings, row.label);\n setLabel(els.remove, this.labels.remove, row.label);\n }\n const valuesKey = row.values.map((v) => `${v.text}${v.color ?? ''}`).join('\\u0001');\n if (valuesKey === els.valuesKey) return;\n els.valuesKey = valuesKey;\n els.values.replaceChildren(...row.values.map((v) => {\n const span = document.createElement('span');\n span.textContent = v.text;\n if (v.color) span.style.color = v.color;\n return span;\n }));\n }\n\n /** Pane rows are placed in their pane; stacked rows flow in the stack. */\n private place(els: RowEls, pane: IndicatorLegendRow['pane']): void {\n const key = pane ? `${Math.round(pane.x)},${Math.round(pane.y)},${Math.round(pane.width)}` : '';\n if (key === els.placeKey) return;\n els.placeKey = key;\n els.el.classList.toggle('tcw-ind-legend-row--pane', pane !== null);\n els.el.style.left = pane ? `${Math.round(pane.x)}px` : '';\n els.el.style.top = pane ? `${Math.round(pane.y)}px` : '';\n els.el.style.maxWidth = pane ? `${Math.max(0, Math.round(pane.width))}px` : '';\n }\n\n private setCollapsed(collapsed: boolean): void {\n this.collapsed = collapsed;\n this.stack.classList.toggle('tcw-ind-legend--collapsed', collapsed);\n }\n\n private overlayCount(): number {\n return this.stack.querySelectorAll(':scope > .tcw-ind-legend-row').length;\n }\n\n /** Written only when something changed: `update()` runs every frame. */\n private renderToggle(count: number): void {\n const shown = count >= COLLAPSE_FROM;\n if (!shown && this.collapsed) this.setCollapsed(false);\n const key = `${shown}|${this.collapsed}|${count}`;\n if (key === this.toggleKey) return;\n this.toggleKey = key;\n this.toggle.hidden = !shown;\n if (!shown) return;\n const label = this.collapsed ? this.labels.expand : this.labels.collapse;\n setLabel(this.toggle, label, this.collapsed ? `(${count})` : undefined);\n this.toggle.setAttribute('aria-expanded', String(!this.collapsed));\n const icon = createIcon(this.collapsed ? 'chevronDown' : 'chevronUp', 12);\n this.toggle.innerHTML = this.collapsed ? `${icon}<span>${count}</span>` : icon;\n }\n}\n\n/**\n * An icon button's name: `title` for the tooltip (\"Remove\"), and an\n * `aria-label` that says what it acts on (\"Remove EMA 50\") for assistive tech,\n * which would otherwise hear a column of identical \"Remove\" buttons. (The\n * tooltip also lifts `title` off the element while it is hovered.)\n */\nfunction setLabel(button: HTMLButtonElement, label: string, subject?: string): void {\n button.title = label;\n button.setAttribute('aria-label', subject ? `${label} ${subject}` : label);\n}\n","import type { IndicatorValue } from '@tradecanvas/commons';\nimport { formatPrice } from '@tradecanvas/commons';\n\n/**\n * Output fields that are not drawn — flags (trend direction, session key, bar\n * colour) and intermediate or running values — so the legend leaves them out.\n * Keep in step with the indicators' `render` in core.\n */\nconst SKIP_KEYS: Readonly<Record<string, readonly string[]>> = {\n psar: ['trend'],\n supertrend: ['trend'],\n svwap: ['session'],\n ao: ['up'],\n voldelta: ['up'],\n chaikinOsc: ['adl'],\n adx: ['dx'],\n lrc: ['slope'],\n ichimoku: ['chikou'],\n};\n\n/**\n * One-line indicators drawn in an up colour (`colors[0]`) or a down colour\n * (`colors[1]`) bar by bar: whether a point is drawn in the up colour.\n */\nconst TWO_TONE: Readonly<Record<string, (point: IndicatorValue) => boolean>> = {\n psar: (p) => p.trend === 1,\n supertrend: (p) => p.trend === 1,\n ao: (p) => p.up === 1,\n voldelta: (p) => p.up === 1,\n chaikinOsc: (p) => (p.value ?? 0) >= 0,\n cmf: (p) => (p.value ?? 0) >= 0,\n dpo: (p) => (p.value ?? 0) >= 0,\n};\n\n/** Indicators that draw in fixed colours of their own, not their style's. */\nconst OWN_COLOURS: ReadonlySet<string> = new Set(['ac']);\n\n/** The finite line values of one indicator output point, in output order. */\nexport function legendNumbers(id: string, point: IndicatorValue | null | undefined): number[] {\n if (!point) return [];\n const skip = SKIP_KEYS[id];\n const numbers: number[] = [];\n for (const key in point) {\n const v = point[key];\n if (typeof v === 'number' && Number.isFinite(v) && !skip?.includes(key)) numbers.push(v);\n }\n return numbers;\n}\n\n/**\n * The colour a one-line indicator is drawn in at `point`, so its value reads\n * as part of the line; null = the neutral text colour.\n */\nexport function legendLineColor(\n id: string,\n colors: readonly string[],\n point: IndicatorValue | null | undefined,\n): string | null {\n if (OWN_COLOURS.has(id)) return null;\n const isUp = TWO_TONE[id];\n if (!isUp) return colors[0] ?? null;\n if (!point) return null;\n return (isUp(point) ? colors[0] : colors[1]) ?? null;\n}\n\n/** Compact formats (\"1.23M\") by locale; the legend formats every frame. */\nconst compactFormats = new Map<string, Intl.NumberFormat>();\n\nfunction compactFormat(locale: string): Intl.NumberFormat {\n let format = compactFormats.get(locale);\n if (!format) {\n format = new Intl.NumberFormat(locale, { notation: 'compact', maximumFractionDigits: 2 });\n compactFormats.set(locale, format);\n }\n return format;\n}\n\n/**\n * A pane indicator's value (RSI 54.32, MACD 0.0012, OBV 1.23M): the decimals\n * follow its size, and big ones are shortened.\n */\nexport function formatIndicatorValue(value: number, locale = 'en-US'): string {\n const size = Math.abs(value);\n if (size >= 1e6) return compactFormat(locale).format(value);\n const digits = size >= 1000 ? 1 : size >= 1 ? 2 : size >= 0.01 ? 4 : 6;\n return formatPrice(value, digits, locale);\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","/**\n * i18n for ChartWidget's own chrome (toolbar, watchlist, indicator picker,\n * status bar, settings panel, hotkey sheet). This does NOT translate\n * data-driven labels sourced from `widgetConfig.ts` (the 69 indicator\n * display names, drawing-tool names, timezone/locale option labels) — those\n * stay in English for now; see README \"Widget i18n\" for the current\n * coverage and how to extend it via `messages`.\n */\n\nexport type MessageKey = typeof EN_MESSAGES extends Record<infer K, string> ? K : never;\n\nexport const EN_MESSAGES = {\n // Toolbar\n 'toolbar.indicators': 'Indicators',\n 'toolbar.indicators.popular': 'Popular',\n 'toolbar.indicators.all': 'All',\n 'indicatorType.overlay': 'overlay',\n 'indicatorType.panel': 'panel',\n 'toolbar.replay': 'Bar replay',\n 'replay.selectHint': 'Click a bar to start the replay',\n 'replay.random': 'Random bar',\n 'replay.realtime': 'Back to realtime',\n 'replay.barsPerSecond': 'bars/s',\n 'replay.play': 'Play',\n 'replay.pause': 'Pause',\n 'replay.stepBack': 'Step back (Shift+←)',\n 'replay.stepForward': 'Step forward (Shift+→)',\n 'toolbar.longBracket': 'Long bracket',\n 'toolbar.shortBracket': 'Short bracket',\n 'toolbar.depthLadder': 'Depth ladder',\n 'toolbar.objects': 'Objects',\n 'toolbar.priceAlerts': 'Price alerts',\n 'toolbar.screenshot': 'Screenshot',\n 'toolbar.settings': 'Chart Settings',\n 'toolbar.toggleTheme': 'Toggle theme',\n 'toolbar.timeframes': 'Timeframes',\n 'toolbar.timeframes.pin': 'Pin to toolbar',\n 'toolbar.fullscreen': 'Fullscreen',\n 'legend.show': 'Show',\n 'legend.hide': 'Hide',\n 'legend.settings': 'Settings',\n 'legend.remove': 'Remove',\n 'legend.collapse': 'Collapse indicators',\n 'legend.expand': 'Show indicators',\n 'toolbar.exitFullscreen': 'Exit fullscreen',\n 'range.presets': 'Visible range',\n 'range.all': 'All',\n 'range.goTo': 'Go to date',\n 'range.goToSubmit': 'Go to',\n 'range.date': 'Date',\n 'range.time': 'Time',\n 'range.cancel': 'Cancel',\n 'range.beforeData': 'Showing the earliest loaded bar',\n\n // Chart types\n 'chartType.candlestick': 'Candlestick',\n 'chartType.line': 'Line',\n 'chartType.area': 'Area',\n 'chartType.bar': 'Bar',\n 'chartType.heikinAshi': 'Heikin-Ashi',\n 'chartType.hollowCandle': 'Hollow Candle',\n 'chartType.baseline': 'Baseline',\n 'chartType.volumeCandles': 'Volume Candles',\n 'chartType.equivolume': 'Equivolume',\n 'chartType.hlcArea': 'HLC Area',\n 'chartType.stepLine': 'Step Line',\n 'chartType.lineWithMarkers': 'Line + Markers',\n\n // Watchlist\n 'watchlist.title': 'Watchlist',\n\n // Status bar / connection\n 'status.connecting': 'Connecting...',\n 'status.live': 'Live',\n 'status.connectionFailed': 'Connection failed',\n 'status.loading': 'Loading chart...',\n\n // Settings panel\n 'settings.title': 'Chart Settings',\n 'settings.tab.style': 'style',\n 'settings.tab.display': 'display',\n 'settings.tab.scale': 'scale',\n 'settings.resetToDefaults': 'Reset to defaults',\n 'settings.done': 'Done',\n 'settings.section.candleColors': 'Candle Colors',\n 'settings.section.background': 'Background',\n\n // Hotkey sheet\n 'hotkeys.title': 'Keyboard shortcuts',\n 'hotkeys.close': 'Close',\n 'hotkeys.gotIt': 'Got it',\n 'hotkeys.group.searchNavigation': 'Search & navigation',\n 'hotkeys.group.chartManipulation': 'Chart manipulation',\n 'hotkeys.group.touch': 'Touch (mobile / tablet)',\n 'hotkeys.group.keyboard': 'Keyboard',\n 'hotkeys.group.drawing': 'Drawing',\n} as const;\n\nexport const VI_MESSAGES: Partial<Record<MessageKey, string>> = {\n 'toolbar.indicators': 'Chỉ báo',\n 'toolbar.indicators.popular': 'Phổ biến',\n 'toolbar.indicators.all': 'Tất cả',\n 'indicatorType.overlay': 'phủ lên',\n 'indicatorType.panel': 'bảng riêng',\n 'toolbar.replay': 'Phát lại',\n 'replay.selectHint': 'Bấm vào một nến để bắt đầu phát lại',\n 'replay.random': 'Nến ngẫu nhiên',\n 'replay.realtime': 'Về thời gian thực',\n 'replay.barsPerSecond': 'nến/giây',\n 'replay.play': 'Phát',\n 'replay.pause': 'Tạm dừng',\n 'replay.stepBack': 'Lùi một nến (Shift+←)',\n 'replay.stepForward': 'Tiến một nến (Shift+→)',\n 'toolbar.longBracket': 'Lệnh Long',\n 'toolbar.shortBracket': 'Lệnh Short',\n 'toolbar.depthLadder': 'Sổ lệnh',\n 'toolbar.objects': 'Đối tượng',\n 'toolbar.priceAlerts': 'Cảnh báo giá',\n 'toolbar.screenshot': 'Chụp màn hình',\n 'toolbar.settings': 'Cài đặt biểu đồ',\n 'toolbar.toggleTheme': 'Đổi giao diện',\n 'toolbar.timeframes': 'Khung thời gian',\n 'toolbar.timeframes.pin': 'Ghim lên thanh công cụ',\n 'toolbar.fullscreen': 'Toàn màn hình',\n 'legend.show': 'Hiện',\n 'legend.hide': 'Ẩn',\n 'legend.settings': 'Cài đặt',\n 'legend.remove': 'Xoá',\n 'legend.collapse': 'Thu gọn chỉ báo',\n 'legend.expand': 'Hiện chỉ báo',\n 'toolbar.exitFullscreen': 'Thoát toàn màn hình',\n 'range.presets': 'Khoảng hiển thị',\n 'range.all': 'Tất cả',\n 'range.goTo': 'Đi tới ngày',\n 'range.goToSubmit': 'Đi tới',\n 'range.date': 'Ngày',\n 'range.time': 'Giờ',\n 'range.cancel': 'Huỷ',\n 'range.beforeData': 'Đang hiện nến sớm nhất đã tải',\n\n 'chartType.candlestick': 'Nến',\n 'chartType.line': 'Đường',\n 'chartType.area': 'Vùng',\n 'chartType.bar': 'Thanh',\n 'chartType.heikinAshi': 'Heikin-Ashi',\n 'chartType.hollowCandle': 'Nến rỗng',\n 'chartType.baseline': 'Đường cơ sở',\n 'chartType.volumeCandles': 'Nến khối lượng',\n 'chartType.equivolume': 'Equivolume',\n 'chartType.hlcArea': 'Vùng HLC',\n 'chartType.stepLine': 'Đường bậc thang',\n 'chartType.lineWithMarkers': 'Đường + điểm đánh dấu',\n\n 'watchlist.title': 'Danh mục theo dõi',\n\n 'status.connecting': 'Đang kết nối...',\n 'status.live': 'Trực tiếp',\n 'status.connectionFailed': 'Kết nối thất bại',\n 'status.loading': 'Đang tải biểu đồ...',\n\n 'settings.title': 'Cài đặt biểu đồ',\n 'settings.tab.style': 'Giao diện',\n 'settings.tab.display': 'Hiển thị',\n 'settings.tab.scale': 'Thang giá',\n 'settings.resetToDefaults': 'Khôi phục mặc định',\n 'settings.done': 'Xong',\n 'settings.section.candleColors': 'Màu nến',\n 'settings.section.background': 'Nền',\n\n 'hotkeys.title': 'Phím tắt',\n 'hotkeys.close': 'Đóng',\n 'hotkeys.gotIt': 'Đã hiểu',\n 'hotkeys.group.searchNavigation': 'Tìm kiếm & điều hướng',\n 'hotkeys.group.chartManipulation': 'Thao tác biểu đồ',\n 'hotkeys.group.touch': 'Cảm ứng (di động / máy tính bảng)',\n 'hotkeys.group.keyboard': 'Bàn phím',\n 'hotkeys.group.drawing': 'Vẽ',\n};\n\nexport const BUILTIN_LOCALES: Record<string, Partial<Record<MessageKey, string>>> = {\n en: EN_MESSAGES,\n vi: VI_MESSAGES,\n};\n\n/**\n * Resolve the widget's message table: built-in English as the base, the\n * requested built-in locale layered on top (falling back key-by-key to\n * English for anything that locale hasn't translated yet), then host\n * `messages` overrides layered last so they always win.\n */\nexport function resolveMessages(\n locale: string | undefined,\n overrides: Partial<Record<MessageKey, string>> | undefined,\n): Record<MessageKey, string> {\n const base = { ...EN_MESSAGES } as Record<MessageKey, string>;\n const localeTable = locale ? BUILTIN_LOCALES[locale] : undefined;\n if (localeTable) Object.assign(base, localeTable);\n if (overrides) Object.assign(base, overrides);\n return base;\n}\n\nexport type Translator = (key: MessageKey) => string;\n\nexport function createTranslator(messages: Record<MessageKey, string>): Translator {\n return (key: MessageKey) => messages[key] ?? EN_MESSAGES[key] ?? key;\n}\n","/**\n * How long a symbol/timeframe switch may run before the loading veil\n * appears. Faster loads just swap the chart in place — flashing a loader for\n * a 150 ms request reads as flicker, not feedback.\n */\nexport const LOADING_SHOW_DELAY_MS = 200;\n\n/**\n * Silhouette of the loading mark: a short rising run of candles as\n * [body top, body height, wick top, wick height, rising] in a 64 px box\n * (y grows downward).\n */\nconst SKELETON_CANDLES: readonly (readonly [number, number, number, number, boolean])[] = [\n [34, 16, 28, 26, false],\n [30, 14, 24, 26, true],\n [26, 18, 20, 30, true],\n [30, 10, 24, 22, false],\n [20, 16, 14, 28, true],\n [14, 18, 8, 30, true],\n [18, 10, 12, 20, false],\n [8, 18, 2, 30, true],\n];\n\n/**\n * Loading state for the chart area: a run of candles lit one after another\n * over a sweeping accent line. The status text is for screen readers only;\n * an error message is shown.\n *\n * - First load (nothing to show yet): opaque skeleton, shown immediately.\n * - Switch (a chart is already on screen): the old chart stays visible and is\n * veiled only if the load outlasts `LOADING_SHOW_DELAY_MS`.\n * - Failure: the label becomes the error message until the next load or a\n * successful retry ends it.\n */\nexport class WidgetLoadingOverlay {\n private readonly el: HTMLDivElement;\n private readonly label: HTMLDivElement;\n private showTimer: ReturnType<typeof setTimeout> | null = null;\n // Starts loading: the widget mounts before its first bars arrive.\n private phase: 'idle' | 'loading' | 'failed' = 'loading';\n\n constructor(parent: HTMLElement, private readonly loadingText: string) {\n this.el = document.createElement('div');\n this.el.className = 'tcw-loading-overlay';\n this.el.setAttribute('role', 'status');\n this.el.setAttribute('aria-live', 'polite');\n\n // Candles + label share a card: transparent on the opaque first-load\n // screen, a raised panel when veiling a chart so it reads over the candles.\n const card = document.createElement('div');\n card.className = 'tcw-loading-card';\n\n const candles = document.createElement('div');\n candles.className = 'tcw-loading-candles';\n candles.setAttribute('aria-hidden', 'true');\n SKELETON_CANDLES.forEach(([bodyTop, bodyHeight, wickTop, wickHeight, rising], i) => {\n const candle = document.createElement('span');\n candle.className = rising ? 'tcw-loading-candle tcw-loading-candle--up' : 'tcw-loading-candle';\n candle.style.setProperty('--tcw-body-top', `${bodyTop}px`);\n candle.style.setProperty('--tcw-body-h', `${bodyHeight}px`);\n candle.style.setProperty('--tcw-wick-top', `${wickTop}px`);\n candle.style.setProperty('--tcw-wick-h', `${wickHeight}px`);\n // A custom property, so a page-wide `animation-delay: 0 !important` reset can't flatten the wave.\n candle.style.setProperty('--tcw-delay', `${i * 110}ms`);\n candles.appendChild(candle);\n });\n card.appendChild(candles);\n\n const track = document.createElement('div');\n track.className = 'tcw-loading-track';\n track.setAttribute('aria-hidden', 'true');\n track.appendChild(document.createElement('span'));\n card.appendChild(track);\n\n this.label = document.createElement('div');\n this.label.className = 'tcw-loading-label';\n this.label.textContent = loadingText;\n card.appendChild(this.label);\n this.el.appendChild(card);\n\n parent.appendChild(this.el);\n }\n\n /**\n * Start a load. `hasContent`: a chart is already on screen to keep showing.\n * `immediate`: skip the show delay — the caller knows the load is slow.\n */\n begin(hasContent: boolean, immediate = false): void {\n this.phase = 'loading';\n this.clearTimer();\n this.label.textContent = this.loadingText;\n this.el.classList.remove('tcw-loading-overlay--error');\n this.el.classList.toggle('tcw-loading-overlay--veil', hasContent);\n if (!hasContent || immediate || this.isShown()) {\n this.el.classList.remove('tcw-loading-overlay--hidden');\n return;\n }\n this.showTimer = setTimeout(() => {\n this.showTimer = null;\n this.el.classList.remove('tcw-loading-overlay--hidden');\n }, LOADING_SHOW_DELAY_MS);\n }\n\n /** The load finished: fade out, or never appear if still within the delay. */\n end(): void {\n this.phase = 'idle';\n this.clearTimer();\n this.el.classList.add('tcw-loading-overlay--hidden');\n }\n\n /** The current load failed (a retry may still be running): show why. */\n fail(message: string): void {\n if (this.phase === 'idle') return;\n this.phase = 'failed';\n this.clearTimer();\n this.label.textContent = message;\n this.el.classList.add('tcw-loading-overlay--error');\n this.el.classList.remove('tcw-loading-overlay--hidden');\n }\n\n /** Whether a load is in progress (begun, not yet ended) — failed included. */\n isActive(): boolean {\n return this.phase !== 'idle';\n }\n\n /** Whether the current load failed and is waiting on a retry. */\n hasFailed(): boolean {\n return this.phase === 'failed';\n }\n\n /** Whether the overlay is on screen (or fading in). */\n isShown(): boolean {\n return !this.el.classList.contains('tcw-loading-overlay--hidden');\n }\n\n destroy(): void {\n this.clearTimer();\n this.el.remove();\n }\n\n private clearTimer(): void {\n if (this.showTimer !== null) {\n clearTimeout(this.showTimer);\n this.showTimer = null;\n }\n }\n}\n","import type { ChartType, DrawingToolType, FeaturesConfig, Theme, TimeFrame } from '@tradecanvas/commons';\nimport { Chart } from '../Chart.js';\nimport { DARK_THEME, LIGHT_THEME } from '@tradecanvas/commons';\nimport type { ActiveIndicatorInfo, ChartWidgetOptions, WidgetState, ChartSettingsState } from './types.js';\nimport { 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, DEFAULT_REPLAY_SPEED } 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 { availableTimeframes, initialTimeframeFavorites, timeframeLabel } from './widgetTimeframes.js';\nimport { WidgetGoToDate, utcToWallTime, wallTimeToUtc } from './WidgetGoToDate.js';\nimport { WidgetTooltip } from './WidgetTooltip.js';\nimport { WidgetIndicatorLegend, type IndicatorLegendRow } from './WidgetIndicatorLegend.js';\nimport { formatIndicatorValue, legendLineColor, legendNumbers } from './legendValues.js';\nimport { RANGE_PRESETS } from '@tradecanvas/core';\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';\nimport { resolveMessages, createTranslator, type Translator } from './i18n.js';\nimport { WidgetLoadingOverlay } from './WidgetLoadingOverlay.js';\n\n/**\n * A local timeframe switch (resampling static data) that took at least this\n * long last time is announced with the loading veil before it runs, since the\n * main thread is about to be busy for several frames.\n */\nconst SLOW_LOCAL_SWITCH_MS = 48;\n/** Base series this long are assumed slow to resample before any timing exists. */\nconst LARGE_SERIES_BARS = 50_000;\n\n/** Upper bound on waiting for a paint — rAF never fires in a frame that isn't rendering. */\nconst PAINT_WAIT_MAX_MS = 100;\n\n/** Resolve once the browser has painted the current DOM state (or gave up waiting). */\nfunction afterPaint(): Promise<void> {\n return new Promise((resolve) => {\n if (typeof requestAnimationFrame !== 'function' || document.hidden) {\n setTimeout(resolve, 0);\n return;\n }\n const fallback = setTimeout(resolve, PAINT_WAIT_MAX_MS);\n requestAnimationFrame(() => setTimeout(() => {\n clearTimeout(fallback);\n resolve();\n }, 0));\n });\n}\n\n/** Distinct line colors for comparison overlays, cycled by add order. */\nconst COMPARE_COLORS = ['#4c8dff', '#a57cff', '#1398a8', '#e25592', '#8a93a3', '#62c895'];\n\n/** Gap between the on-chart indicator rows and the plot or pane edge, px. */\nconst LEGEND_INSET = 4;\n\n/** The widget pressed last: with several on a page, Alt+ shortcuts act on that one. */\nlet lastPressedWidget: ChartWidget | null = null;\n\n/** 1 when bar times are milliseconds, 1000 when they are seconds. */\nconst barTimeUnit = (data: ReadonlyArray<{ time: number }>): number =>\n (data[data.length - 1]?.time ?? 0) > 1e12 ? 1 : 1000;\n\nconst isTyping = (): boolean => {\n const active = document.activeElement as HTMLElement | null;\n return !!active && (active.tagName === 'INPUT' || active.tagName === 'TEXTAREA' || active.tagName === 'SELECT' || active.isContentEditable);\n};\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 goToDate: WidgetGoToDate | null = null;\n private readonly tooltip: WidgetTooltip;\n private indicatorLegend: WidgetIndicatorLegend | null = null;\n private legendFrame = 0;\n /**\n * Modals (settings, search, command palette, hotkeys) mount here: it carries\n * the theme tokens to `document.body`, and moves inside the widget while\n * the widget is fullscreen, where nothing outside it is shown.\n */\n private readonly portal = document.createElement('div');\n private readonly overlayHost = (): HTMLElement => {\n const host = document.fullscreenElement === this.root ? this.root : document.body;\n if (this.portal.parentElement !== host) host.appendChild(this.portal);\n return this.portal;\n };\n private readonly onRootPointerDown = () => { lastPressedWidget = this; };\n private readonly onFullscreenChange = () => {\n this.toolbar?.setFullscreen(document.fullscreenElement === this.root);\n if (this.portal.isConnected) this.overlayHost(); // an open modal follows\n };\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 /** The bar the on-chart indicator values are read at; null = the latest. */\n private legendHoverIndex: number | null = null;\n private favoritesStore = new DrawingFavoritesStore();\n /** Timeframes pinned to the toolbar (same store shape as drawing favourites). */\n private timeframeFavorites = new DrawingFavoritesStore('tcw:tf-favorites');\n /** Timeframes on offer, shortest first. */\n private timeframes: TimeFrame[] = [];\n private watchlist: WidgetWatchlist | null = null;\n private watchlistSparkBuffer = new Map<string, number[]>();\n private sessionRefPrice: number | null = null;\n /** Per-symbol refPrice explicitly pushed by the host via `setWatchlistEntry` — takes precedence over `sessionRefPrice`. */\n private hostWatchlistRefPrice = new Map<string, number>();\n private watchlistInterval: ReturnType<typeof setInterval> | null = null;\n private replayPollInterval: ReturnType<typeof setInterval> | null = null;\n /** Bars revealed per second. */\n private replaySpeed = DEFAULT_REPLAY_SPEED;\n /** While picking the start bar: shades the bars right of the pointer. */\n private replayShade: HTMLDivElement | null = null;\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 loading: WidgetLoadingOverlay;\n /** Bumped per stream connect; a connect that is no longer the latest leaves the UI to the newer one. */\n private connectSeq = 0;\n /** Bumped per local resample and widget.setData; a deferred local switch that is no longer the latest is skipped. */\n private localSeq = 0;\n /** Duration of the last local resample + setData, for SLOW_LOCAL_SWITCH_MS. */\n private lastLocalSwitchMs = 0;\n private destroyed = false;\n private options: ChartWidgetOptions;\n private symbols: string[];\n private settingsState: ChartSettingsState;\n private t: Translator;\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 // `numberLocale` lives in two places: the headless Chart gets it via\n // `chartOptions` (spread straight into `new Chart()` below) — but the\n // widget's own chrome (watchlist, alerts, hotkey sheet, settings panel)\n // reads `settingsState.numberLocale`, which otherwise stays on\n // DEFAULT_SETTINGS' 'en-US' until the host touches the Settings UI.\n // Seed it from the same option so both layers start in sync.\n this.settingsState = {\n ...DEFAULT_SETTINGS,\n ...(options.chartOptions?.numberLocale ? { numberLocale: options.chartOptions.numberLocale } : {}),\n };\n this.t = createTranslator(resolveMessages(options.locale, options.messages));\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 // The chart's feature flags; controls for switched-off features are left out.\n // Host overrides win per key (see the Chart below).\n const features: FeaturesConfig = {\n drawings: true,\n drawingMagnet: true,\n drawingUndoRedo: true,\n indicators: true,\n trading: options.trading !== false,\n tradingContextMenu: false,\n volume: true,\n legend: true,\n crosshair: true,\n // Pro trading charts have no cursor-following OHLCV popup — just the\n // legend, which ChartWidget already renders. Off by default here\n // (the headless Chart's own default stays `true`); opt back in via\n // `chartOptions: { features: { crosshairTooltip: true } }`.\n crosshairTooltip: false,\n keyboard: true,\n screenshot: true,\n alerts: true,\n barCountdown: true,\n logScale: true,\n watermark: true,\n ...options.chartOptions?.features,\n };\n\n this.timeframes = availableTimeframes(options.timeframes, features.timeframes);\n // First run, or none of the saved pins is on offer here: start from the defaults.\n if (!this.timeframes.some((tf) => this.timeframeFavorites.has(tf))) {\n const initial = initialTimeframeFavorites(this.timeframes, features.defaultTimeframeFavorites, !!options.timeframes?.length);\n for (const tf of initial) this.timeframeFavorites.add(tf);\n }\n const requestedTimeframe = options.timeframe ?? '5m';\n const startTimeframe = !features.timeframes?.length || features.timeframes.includes(requestedTimeframe)\n ? requestedTimeframe\n : this.timeframes[0] ?? requestedTimeframe;\n\n // Initialize state\n this.state = {\n symbol: options.symbol ?? this.symbols[0] ?? 'BTCUSDT',\n timeframe: startTimeframe,\n chartType: options.chartOptions?.chartType ?? 'candlestick',\n isDark,\n activeIndicators: new Map(),\n activeTool: null,\n magnetEnabled: features.drawingMagnet !== false,\n stayInDrawing: false,\n // Static data (no adapter) has no connection to report.\n connectionState: options.adapter ? 'connecting' : 'disconnected',\n connectionMessage: options.adapter ? this.t('status.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 this.tooltip = new WidgetTooltip(this.root);\n this.portal.className = 'tcw-root tcw-portal';\n this.portal.dataset.tcwTheme = this.root.dataset.tcwTheme;\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: this.timeframes.map((value) => ({ value, label: timeframeLabel(value) })),\n timeframeFavorites: this.pinnedTimeframes(),\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 onToggleTimeframeFavorite: (tf) => this.handleToggleTimeframeFavorite(tf),\n onChartType: (type) => this.handleChartType(type),\n onAddIndicator: (id) => this.handleAddIndicator(id),\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 onToggleFullscreen: options.fullscreen !== false && typeof document !== 'undefined' && document.fullscreenEnabled\n ? () => this.toggleFullscreen()\n : undefined,\n },\n this.t,\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: features.drawingMagnet !== false ? () => this.handleToggleMagnet() : undefined,\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 onToggleStayInDrawing: () => this.handleToggleStayInDrawing(),\n },\n );\n }\n\n this.chartContainer = document.createElement('div');\n this.chartContainer.className = 'tcw-chart-container';\n body.appendChild(this.chartContainer);\n\n // Loading state: covers the empty chart until the first\n // bars land, then veils the previous chart during slow switches.\n this.loading = new WidgetLoadingOverlay(this.chartContainer, this.t('status.loading'));\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 }, this.t('watchlist.title'));\n this.watchlist.setActive(this.state.symbol);\n this.watchlist.setLocale(this.settingsState.numberLocale || undefined);\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 ...options.chartOptions,\n // `features` is merged explicitly (host overrides win per-key) rather\n // than inherited wholesale from the `...options.chartOptions` spread\n // above — otherwise passing e.g. `chartOptions: { features: { x } }`\n // would silently drop every other default.\n features,\n });\n\n // New bars end the loading state, whoever supplied them (stream snapshot,\n // widget.setData, or the host calling getChart().setData directly); stream\n // errors surface in the status bar and, mid-load, on the loading veil.\n this.chart.on('dataUpdate', (e) => this.handleDataUpdate(e.payload));\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 const range = options.rangeBar !== false;\n this.statusBar = new WidgetStatusBar(this.root, range ? {\n presets: RANGE_PRESETS,\n presetLabels: { All: this.t('range.all') },\n groupLabel: this.t('range.presets'),\n goToLabel: this.t('range.goTo'),\n onPreset: (preset) => this.chart.setVisibleRangePreset(preset),\n onGoTo: () => this.toggleGoToDate(),\n } : undefined);\n if (range) {\n this.goToDate = new WidgetGoToDate(this.root, {\n title: this.t('range.goTo'),\n date: this.t('range.date'),\n time: this.t('range.time'),\n submit: this.t('range.goToSubmit'),\n cancel: this.t('range.cancel'),\n }, ({ date, time }) => this.goToWallTime(date, time));\n }\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 }, this.t, { barCountdown: features.barCountdown, logScale: features.logScale }, this.overlayHost);\n }\n\n // 8a. Symbol search\n this.symbolSearch = new WidgetSymbolSearch({\n onPick: (sym) => { void this.setSymbol(sym); },\n onClose: () => {},\n }, this.overlayHost);\n this.hotkeySheet = new WidgetHotkeySheet({ onClose: () => {} }, this.t, this.overlayHost);\n\n // The sidebar follows the chart's drawing tool: finished, cancelled with\n // Esc, or kept for the next drawing in stay-in-drawing mode.\n this.chart.on('drawingToolChange', (e) => {\n const tool = (e.payload as { tool: DrawingToolType | null }).tool;\n if (tool === this.state.activeTool) return;\n this.state = { ...this.state, activeTool: tool };\n this.updateUI();\n });\n\n // The indicator list mirrors the chart's indicators, whoever adds or removes them.\n this.chart.on('indicatorAdd', () => this.syncIndicatorsFromChart());\n this.chart.on('indicatorRemove', () => this.syncIndicatorsFromChart());\n\n // The indicators on the chart itself, instead of toolbar chips that overflow.\n if (options.indicatorLegend !== false) {\n this.chart.setPaneTitlesVisible(false);\n this.indicatorLegend = new WidgetIndicatorLegend(this.chartContainer, {\n onToggleVisible: (iid, visible) => {\n this.chart.setIndicatorVisible(iid, visible);\n this.scheduleLegend();\n if (this.objectTree?.isOpen()) this.refreshObjects();\n },\n onSettings: (iid) => this.openIndicatorSettings(iid),\n onRemove: (iid) => this.handleRemoveIndicator(iid),\n }, {\n show: this.t('legend.show'),\n hide: this.t('legend.hide'),\n settings: this.t('legend.settings'),\n remove: this.t('legend.remove'),\n collapse: this.t('legend.collapse'),\n expand: this.t('legend.expand'),\n });\n this.chart.on('crosshairMove', (e) => {\n const p = e.payload as { barIndex?: number };\n this.legendHoverIndex = typeof p.barIndex === 'number' ? p.barIndex : null;\n this.scheduleLegend();\n });\n // Off the chart, the values go back to the latest bar.\n this.chart.on('crosshairLeave', () => {\n this.legendHoverIndex = null;\n this.scheduleLegend();\n });\n for (const event of ['indicatorUpdate', 'dataUpdate', 'resize', 'paneResize', 'themeChange'] as const) {\n this.chart.on(event, () => this.scheduleLegend());\n }\n }\n\n // Replay: while picking, a click starts the replay at that bar; during a\n // replay it jumps the 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.replayBar.getMode() === 'select') {\n this.startReplayAt(idx);\n return;\n }\n if (this.chart.getReplayState() === 'playing') this.chart.replayPause();\n this.chart.replaySeek(idx);\n this.replayBar.setState('paused');\n });\n // While picking the start bar, shade the bars that would be hidden.\n this.chart.on('crosshairMove', (e) => {\n if (this.replayBar?.getMode() !== 'select' || !this.replayBar.isMounted()) return;\n const point = (e.payload as { point?: { x: number } | null }).point;\n this.positionReplayShade(point?.x ?? null);\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) => {\n this.chart.updateIndicator(instanceId, params);\n this.syncIndicatorsFromChart(); // the chip shows the parameters\n },\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 this.scheduleLegend();\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: features.compareSymbols !== false ? () => this.handleAddCompare() : undefined,\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 }, this.overlayHost);\n\n this.boundGlobalKeydown = (e: KeyboardEvent) => {\n if (this.replayBar?.isMounted() && this.handleReplayKey(e)) return;\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.altKey && !e.ctrlKey && !e.metaKey && (e.code === 'KeyI' || e.code === 'KeyG')) {\n // By key position: on macOS Alt+G types \"©\".\n if (isTyping() || (lastPressedWidget !== null && lastPressedWidget !== this)) return;\n if (e.code === 'KeyI') {\n // Alt+I → invert the price scale.\n e.preventDefault();\n this.applySettings({ invertScale: !this.settingsState.invertScale });\n } else if (this.goToDate) {\n // Alt+G → go to date.\n e.preventDefault();\n this.toggleGoToDate();\n }\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 document.addEventListener('fullscreenchange', this.onFullscreenChange);\n this.root.addEventListener('pointerdown', this.onRootPointerDown, true);\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 * A host-supplied `refPrice` takes precedence over the widget's own\n * session-open guess for that symbol — including the active one, so the\n * auto-tick loop stops clobbering it (see `tickWatchlist`).\n */\n setWatchlistEntry(symbol: string, entry: Partial<WatchlistEntry>): void {\n if (entry.refPrice !== undefined) {\n this.hostWatchlistRefPrice.set(symbol, entry.refPrice);\n }\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 const hostRef = this.hostWatchlistRefPrice.get(this.state.symbol);\n // Reference price: first bar of the loaded slice — that's the closest\n // approximation of \"session open\" without timezone bookkeeping. Only\n // used as a fallback; a refPrice the host already pushed via\n // `setWatchlistEntry` (even for the active symbol) always wins.\n if (hostRef === undefined && 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: hostRef ?? this.sessionRefPrice ?? data[0].open,\n sparkline: buf.slice(),\n });\n }\n\n /** Ignored when the chart's `features.timeframes` whitelist leaves `tf` out. */\n async setTimeframe(tf: TimeFrame): Promise<void> {\n if (!this.chart.isTimeframeAllowed(tf)) return;\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 await 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 await this.switchLocalTimeframe();\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.portal.dataset.tcwTheme = this.root.dataset.tcwTheme;\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 document.removeEventListener('fullscreenchange', this.onFullscreenChange);\n this.root.removeEventListener('pointerdown', this.onRootPointerDown, true);\n this.tooltip.destroy();\n if (this.legendFrame) cancelAnimationFrame(this.legendFrame);\n this.indicatorLegend?.destroy();\n if (lastPressedWidget === this) lastPressedWidget = null;\n this.portal.remove();\n if (document.fullscreenElement === this.root) void document.exitFullscreen().catch(() => {});\n this.flushActiveLayout();\n this.commandPalette?.destroy();\n this.symbolSearch?.destroy();\n this.hotkeySheet?.destroy();\n if (this.replayPollInterval) clearInterval(this.replayPollInterval);\n this.replayShade?.remove();\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.goToDate?.destroy();\n this.loading.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 // what users expect from professional trading terminals.\n this.symbolSearch?.open(this.symbols, this.state.symbol);\n }\n\n private handleTimeframe(tf: TimeFrame): void {\n void this.setTimeframe(tf);\n }\n\n /** Fill the screen with the widget, or leave fullscreen. */\n toggleFullscreen(): void {\n if (document.fullscreenElement === this.root) {\n void document.exitFullscreen().catch(() => {});\n return;\n }\n this.root.requestFullscreen().catch((err: unknown) => {\n this.toast(err instanceof Error ? err.message : 'Fullscreen is not available', 'error');\n });\n }\n\n /** The display timezone from the settings: minutes east of UTC, null = local. */\n private displayTzOffset(): number | null {\n const tz = this.settingsState.timezone;\n return tz === 'local' || !Number.isFinite(Number(tz)) ? null : Number(tz);\n }\n\n private toggleGoToDate(): void {\n if (!this.goToDate) return;\n if (this.goToDate.isOpen()) {\n this.goToDate.close();\n return;\n }\n const data = this.chart.getData();\n if (data.length === 0) return;\n this.goToDate.open(\n utcToWallTime(data[data.length - 1].time * barTimeUnit(data), this.displayTzOffset()),\n this.root.querySelector('[data-role=\"goto\"]'),\n );\n }\n\n private goToWallTime(date: string, time: string): void {\n const ms = wallTimeToUtc(date, time, this.displayTzOffset());\n const data = this.chart.getData();\n if (ms === null || data.length === 0) return;\n const ts = ms / barTimeUnit(data); // the bars' own unit\n this.chart.goToTime(ts);\n if (ts < data[0].time) this.toast(this.t('range.beforeData'));\n }\n\n /** Pinned timeframes that are still on offer, shortest first. */\n private pinnedTimeframes(): TimeFrame[] {\n const pinned = this.timeframeFavorites.list();\n return this.timeframes.filter((tf) => pinned.includes(tf));\n }\n\n private handleToggleTimeframeFavorite(tf: TimeFrame): void {\n this.timeframeFavorites.toggle(tf);\n this.toolbar?.setTimeframeFavorites(this.pinnedTimeframes());\n this.updateUI();\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.localSeq++; // supersedes a local switch still waiting to run\n this.baseSeries = data;\n this.baseTimeframeMs = inferTimeframeMs(data);\n this.applyTimeframeData();\n // Static data is loaded the moment it's set, even an empty series. With a\n // live adapter the stream's own load decides (connectStream).\n if (!this.adapter) this.loading.end();\n }\n\n /**\n * Local timeframe switch. When it is expected to block the main thread for\n * several frames, veil the chart first and let that paint — otherwise the\n * click would look ignored until the new chart pops in.\n */\n private async switchLocalTimeframe(): Promise<void> {\n if (!this.baseSeries) return;\n const seq = ++this.localSeq;\n const expectSlow = this.lastLocalSwitchMs >= SLOW_LOCAL_SWITCH_MS\n || this.baseSeries.length >= LARGE_SERIES_BARS;\n try {\n if (expectSlow) {\n this.loading.begin(this.chart.getData().length > 0, true);\n await afterPaint();\n // Superseded: the newer switch or setData() ends the loading state.\n if (seq !== this.localSeq || this.destroyed) return;\n }\n this.applyTimeframeData();\n } finally {\n // Also on a throw (bad data, a failing custom indicator) — never leave\n // the veil up.\n if (seq === this.localSeq) this.loading.end();\n }\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 started = performance.now();\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 this.lastLocalSwitchMs = performance.now() - started;\n }\n\n private handleDataUpdate(payload: unknown): void {\n if (!payload || typeof payload !== 'object') return;\n const p = payload as { length?: number; error?: string; connection?: { state?: string } };\n if (typeof p.length === 'number') {\n if (p.length > 0 && this.loading.isActive()) {\n this.loading.end();\n // A retry after a failed load just delivered history.\n if (this.state.connectionState === 'error') this.setConnectionState('connected', this.t('status.live'));\n }\n return;\n }\n if (p.error !== undefined) {\n // Only a failed *load* is reported from the error itself. Errors outside\n // one can be transient (a single failed poll on a healthy connection);\n // the status bar follows the stream's connection state below instead.\n if (this.loading.isActive()) {\n this.loading.fail(this.t('status.connectionFailed'));\n this.setConnectionState('error', p.error || this.t('status.connectionFailed'));\n }\n return;\n }\n switch (p.connection?.state) {\n case 'connected':\n // A retry that brought back an empty history ends a failed load too.\n if (this.loading.hasFailed()) this.loading.end();\n if (!this.loading.isActive() && this.state.connectionState !== 'connected') {\n this.setConnectionState('connected', this.t('status.live'));\n }\n break;\n case 'reconnecting':\n if (!this.loading.isActive()) this.setConnectionState('connecting', this.t('status.connecting'));\n break;\n case 'error':\n if (!this.loading.isActive()) this.setConnectionState('error', this.t('status.connectionFailed'));\n break;\n }\n }\n\n private setConnectionState(connectionState: WidgetState['connectionState'], connectionMessage: string): void {\n this.state = { ...this.state, connectionState, connectionMessage };\n this.updateUI();\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.keys()]) this.chart.removeIndicator(instanceId);\n for (const ind of s.indicators) this.chart.addIndicator(ind.id, ind.params);\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 /**\n * Add another instance — picking EMA twice gives two EMAs (e.g. 20 and 50\n * once their settings are changed). Remove one from its chip.\n */\n private handleAddIndicator(indId: string): void {\n this.chart.addIndicator(indId); // the chip strip follows the indicatorAdd event\n }\n\n private handleRemoveIndicator(instanceId: string): void {\n this.chart.removeIndicator(instanceId);\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.values()].some((a) => a.id === 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 this.timeframes) {\n items.push({\n id: tf,\n label: timeframeLabel(tf),\n category: 'timeframe',\n active: this.state.timeframe === tf,\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 handleToggleStayInDrawing(): void {\n const stayInDrawing = !this.state.stayInDrawing;\n this.state = { ...this.state, stayInDrawing };\n this.chart.setStayInDrawingMode(stayInDrawing);\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.portal.dataset.tcwTheme = this.root.dataset.tcwTheme;\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.syncIndicatorsFromChart();\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 /** Rebuild the chip strip from the chart's indicator instances. */\n private syncIndicatorsFromChart(): void {\n const next = new Map<string, ActiveIndicatorInfo>();\n for (const a of this.chart.getActiveIndicators()) {\n next.set(a.instanceId, { id: a.id, label: indicatorChipLabel(a.id, a.params, a.descriptor.defaultConfig) });\n }\n this.state = { ...this.state, activeIndicators: next };\n this.updateUI();\n }\n\n // --- Replay ---\n\n /** Open (or close) bar replay with its scrubber — what the toolbar's Replay button does. */\n toggleReplay(): void {\n if (this.replayBar?.isMounted()) {\n this.exitReplay();\n } else {\n this.enterReplay();\n }\n }\n\n /**\n * Open replay in \"pick a start bar\" mode: the bars right of the pointer\n * are shaded, and a click cuts the chart there and waits paused. Play\n * starts from a default point; \"random bar\" picks one.\n */\n private enterReplay(): void {\n if (this.replayTotal() < 2) return;\n\n const t = this.t;\n this.replayBar = new WidgetReplayBar(\n {\n onPlay: () => {\n if (this.replayBar?.getMode() === 'select') {\n this.startReplayAt(Math.max(1, this.replayTotal() - 100), true);\n return;\n }\n if (this.chart.getReplayState() === 'paused') this.chart.replayResume();\n this.replayBar?.setState('playing');\n },\n onPause: () => {\n this.chart.replayPause();\n this.replayBar?.setState('paused');\n },\n onStepBack: () => this.stepReplay(-1),\n onStepForward: () => this.stepReplay(1),\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: (barsPerSecond) => {\n this.replaySpeed = barsPerSecond;\n this.chart.setReplaySpeed(barsPerSecond);\n },\n onRandomStart: () => {\n const n = this.replayTotal();\n // Somewhere in the middle 80%, so there is history before and bars after.\n const lo = Math.max(1, Math.floor(n * 0.1));\n const hi = Math.max(lo, Math.floor(n * 0.9));\n this.startReplayAt(lo + Math.floor(Math.random() * (hi - lo + 1)));\n },\n onClose: () => this.exitReplay(),\n },\n {\n selectHint: t('replay.selectHint'),\n random: t('replay.random'),\n realtime: t('replay.realtime'),\n barsPerSecond: t('replay.barsPerSecond'),\n play: t('replay.play'),\n pause: t('replay.pause'),\n stepBack: t('replay.stepBack'),\n stepForward: t('replay.stepForward'),\n },\n );\n this.replayBar.mount(this.chartContainer, { total: this.replayTotal(), speed: this.replaySpeed, mode: 'select' });\n\n this.replayShade = document.createElement('div');\n this.replayShade.className = 'tcw-replay-shade';\n this.replayShade.hidden = true;\n this.chartContainer.appendChild(this.replayShade);\n this.chartContainer.addEventListener('mouseleave', this.hideReplayShade);\n }\n\n private readonly hideReplayShade = (): void => this.positionReplayShade(null);\n\n /**\n * Open replay (if it isn't open) and start it at bar `index` — paused, or\n * playing when `play` is set — skipping the pick-a-bar step.\n */\n replayFrom(index: number, play = false): void {\n if (!this.replayBar?.isMounted()) this.enterReplay();\n this.startReplayAt(index, play);\n }\n\n /** Cut the chart at `index` and wait paused (or play at once). */\n private startReplayAt(index: number, play = false): void {\n const bar = this.replayBar;\n if (!bar) return;\n const n = this.replayTotal();\n const start = Math.max(0, Math.min(Number.isFinite(index) ? Math.floor(index) : 0, n - 1));\n this.replayShade?.remove();\n this.replayShade = null;\n this.chartContainer.removeEventListener('mouseleave', this.hideReplayShade);\n bar.setMode('replay');\n this.chart.replayStart({ speed: this.replaySpeed, interval: 1000, startIndex: start, paused: true });\n if (play) this.chart.replayResume();\n bar.setState(play ? 'playing' : 'paused');\n this.syncReplayBar();\n\n if (this.replayPollInterval) clearInterval(this.replayPollInterval);\n this.replayPollInterval = setInterval(() => this.syncReplayBar(), 150);\n }\n\n /** Bars available to replay: the whole series, not the slice on screen. */\n private replayTotal(): number {\n return this.chart.isReplayActive() ? this.chart.getReplayProgress().total : this.chart.getData().length;\n }\n\n /** Mirror the replay engine in the bar; close it if the session ended elsewhere. */\n private syncReplayBar(): void {\n const bar = this.replayBar;\n if (!bar?.isMounted() || bar.getMode() !== 'replay') return;\n if (!this.chart.isReplayActive()) {\n // e.g. a symbol or timeframe switch replaced the series.\n this.teardownReplayUi();\n return;\n }\n const p = this.chart.getReplayProgress();\n const state = this.chart.getReplayState();\n bar.setProgress(p.current, p.total);\n bar.setState(state === 'stopped' ? 'paused' : state);\n bar.setEnded(state !== 'playing' && p.total > 0 && p.current >= p.total - 1);\n }\n\n private stepReplay(delta: number): void {\n if (this.replayBar?.getMode() !== 'replay') return;\n const p = this.chart.getReplayProgress();\n if (this.chart.getReplayState() === 'playing') this.chart.replayPause();\n this.chart.replaySeek(Math.max(0, Math.min(p.total - 1, p.current + delta)));\n this.replayBar.setState('paused');\n this.syncReplayBar();\n }\n\n /** Replay shortcuts: Shift+←/→ step one bar; Escape cancels picking a start bar. */\n private handleReplayKey(e: KeyboardEvent): boolean {\n if (e.defaultPrevented) return false;\n const active = document.activeElement as HTMLElement | null;\n if (active && (active.tagName === 'INPUT' || active.tagName === 'TEXTAREA' || active.tagName === 'SELECT' || active.isContentEditable)) {\n return false;\n }\n if (e.shiftKey && (e.key === 'ArrowRight' || e.key === 'ArrowLeft') && this.replayBar?.getMode() === 'replay') {\n e.preventDefault();\n // The chart's own Shift+Arrow scrolls ten bars; this one steps the replay.\n e.stopPropagation();\n this.stepReplay(e.key === 'ArrowRight' ? 1 : -1);\n return true;\n }\n if (e.key === 'Escape' && this.replayBar?.getMode() === 'select') {\n this.exitReplay();\n return true;\n }\n return false;\n }\n\n private positionReplayShade(x: number | null): void {\n const shade = this.replayShade;\n if (!shade) return;\n const plot = this.chart.getPlotRect();\n if (x === null || x < plot.x || x > plot.x + plot.width) {\n shade.hidden = true;\n return;\n }\n shade.hidden = false;\n shade.style.left = `${x}px`;\n shade.style.top = `${plot.y}px`;\n shade.style.width = `${plot.x + plot.width - x}px`;\n shade.style.height = `${plot.height}px`;\n }\n\n /** Leave replay and return to the live series (with updates that arrived meanwhile). */\n private exitReplay(): void {\n this.teardownReplayUi();\n this.chart.replayStop();\n }\n\n private teardownReplayUi(): void {\n if (this.replayPollInterval) {\n clearInterval(this.replayPollInterval);\n this.replayPollInterval = null;\n }\n this.replayShade?.remove();\n this.replayShade = null;\n this.chartContainer.removeEventListener('mouseleave', this.hideReplayShade);\n this.replayBar?.unmount();\n this.replayBar = null;\n }\n\n private applySettings(patch: Partial<ChartSettingsState>): void {\n this.settingsState = { ...this.settingsState, ...patch };\n this.scheduleLegend(); // the OHLCV legend's rows and the locale move or reword it\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.invertScale !== undefined) this.chart.setInvertScale(patch.invertScale);\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) {\n this.chart.setNumberLocale(patch.numberLocale);\n this.watchlist?.setLocale(patch.numberLocale || undefined);\n }\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 const seq = ++this.connectSeq;\n\n this.state = {\n ...this.state,\n connectionState: 'connecting',\n connectionMessage: this.t('status.connecting'),\n };\n this.updateUI();\n // Keep the previous chart up while the next one loads; it only gets the\n // veil if the request is slow (see WidgetLoadingOverlay).\n this.loading.begin(this.chart.getData().length > 0);\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 // A newer switch started while this one was loading — it owns the UI now.\n if (seq !== this.connectSeq || this.destroyed) return;\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 if (this.loading.hasFailed()) {\n // History failed to load; the stream keeps retrying and the next\n // snapshot ends the loading state (handleDataUpdate).\n this.state = { ...this.state, connectionState: 'error' };\n } else {\n this.loading.end();\n this.state = {\n ...this.state,\n connectionState: 'connected',\n connectionMessage: this.t('status.live'),\n };\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 if (seq !== this.connectSeq || this.destroyed) return;\n this.loading.fail(this.t('status.connectionFailed'));\n this.state = {\n ...this.state,\n connectionState: 'error',\n connectionMessage: err instanceof Error ? err.message : this.t('status.connectionFailed'),\n };\n }\n\n this.updateUI();\n }\n\n /** Redraw the on-chart indicator list on the next frame (coalesced). */\n private scheduleLegend(): void {\n if (!this.indicatorLegend || this.legendFrame) return;\n this.legendFrame = requestAnimationFrame(() => {\n this.legendFrame = 0;\n this.renderLegend();\n });\n }\n\n private renderLegend(): void {\n if (!this.indicatorLegend || this.destroyed) return;\n const last = this.chart.getData().length - 1;\n // Renko, Kagi and the like redraw the series: the hovered bar is not a\n // data bar, so their values stay on the latest one.\n const hover = this.chart.isTimeAligned() ? this.legendHoverIndex : null;\n const idx = hover === null ? last : Math.min(Math.max(hover, 0), last);\n const panes = new Map(this.chart.getIndicatorPanes().map((p) => [p.instanceId, p.rect]));\n const locale = this.settingsState.numberLocale || 'en-US';\n const rows: IndicatorLegendRow[] = this.chart.getActiveIndicators().map((ind) => {\n const pane = panes.get(ind.instanceId) ?? null;\n const series = this.chart.getIndicatorOutput(ind.instanceId)?.series;\n const point = idx >= 0 ? series?.[idx] : null;\n const numbers = legendNumbers(ind.id, point);\n // One line (judged at the latest bar, past any warm-up): the line's\n // colour there. Several: which value is which line isn't known here,\n // so they share the neutral colour rather than guess.\n const lines = idx === last ? numbers.length : legendNumbers(ind.id, last >= 0 ? series?.[last] : null).length;\n const color = lines === 1 ? legendLineColor(ind.id, this.chart.getIndicatorStyle(ind.instanceId)?.colors ?? [], point) : null;\n return {\n instanceId: ind.instanceId,\n label: indicatorChipLabel(ind.id, ind.params, ind.descriptor.defaultConfig),\n visible: ind.visible,\n values: numbers.map((v) => ({ text: pane ? formatIndicatorValue(v, locale) : this.chart.formatPrice(v), color })),\n pane: pane ? { x: pane.x + LEGEND_INSET, y: pane.y + 1, width: pane.width - 2 * LEGEND_INSET } : null,\n };\n });\n const plot = this.chart.getPlotRect();\n this.indicatorLegend.update(rows, { left: plot.x + LEGEND_INSET, top: this.chart.getLegendBottom() + 1 });\n }\n\n private updateUI(): void {\n this.scheduleLegend();\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\n/**\n * \"EMA 20\", \"BB 20 2\", \"MACD 12 26 9\": the short name plus up to three\n * numeric parameters, in the indicator's own order, so two instances of the\n * same indicator can be told apart.\n */\nexport function indicatorChipLabel(\n id: string,\n params: Record<string, unknown>,\n defaults?: Record<string, unknown>,\n): string {\n const order = defaults ? Object.keys(defaults) : Object.keys(params);\n const numbers = order\n .map((k) => params[k])\n .filter((v): v is number => typeof v === 'number' && Number.isFinite(v))\n .slice(0, 3)\n .map((v) => String(Number(v.toFixed(4))));\n return [id.toUpperCase(), ...numbers].join(' ');\n}\n"],"mappings":"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"}