@tradecanvas/chart 0.9.0 → 1.0.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 (81) hide show
  1. package/dist/Chart.d.ts +148 -5
  2. package/dist/Chart.d.ts.map +1 -1
  3. package/dist/{DragDropImporter-6QOjnfSj.js → DragDropImporter-C4x09P7e.js} +446 -112
  4. package/dist/DragDropImporter-C4x09P7e.js.map +1 -0
  5. package/dist/DragDropImporter-DeXlngof.cjs +2 -0
  6. package/dist/DragDropImporter-DeXlngof.cjs.map +1 -0
  7. package/dist/charts/ChartTypeStrategy.d.ts +13 -0
  8. package/dist/charts/ChartTypeStrategy.d.ts.map +1 -1
  9. package/dist/finance/PerformanceDashboard.d.ts +43 -0
  10. package/dist/finance/PerformanceDashboard.d.ts.map +1 -0
  11. package/dist/finance/index.d.ts +4 -0
  12. package/dist/finance/index.d.ts.map +1 -1
  13. package/dist/finance/performanceData.d.ts +39 -0
  14. package/dist/finance/performanceData.d.ts.map +1 -0
  15. package/dist/index.cjs +1 -1
  16. package/dist/index.cjs.map +1 -1
  17. package/dist/index.d.ts +8 -4
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +293 -36
  20. package/dist/index.js.map +1 -1
  21. package/dist/io/index.d.ts +2 -0
  22. package/dist/io/index.d.ts.map +1 -1
  23. package/dist/io/resampleOHLCV.d.ts +29 -0
  24. package/dist/io/resampleOHLCV.d.ts.map +1 -0
  25. package/dist/plugins/PluginManager.d.ts +27 -1
  26. package/dist/plugins/PluginManager.d.ts.map +1 -1
  27. package/dist/plugins/contracts.d.ts +54 -0
  28. package/dist/plugins/contracts.d.ts.map +1 -0
  29. package/dist/plugins/index.d.ts +4 -0
  30. package/dist/plugins/index.d.ts.map +1 -1
  31. package/dist/plugins/registry.d.ts +10 -0
  32. package/dist/plugins/registry.d.ts.map +1 -0
  33. package/dist/trading/wireExecution.d.ts +26 -0
  34. package/dist/trading/wireExecution.d.ts.map +1 -0
  35. package/dist/widget/AlertNotifier.d.ts +32 -0
  36. package/dist/widget/AlertNotifier.d.ts.map +1 -0
  37. package/dist/widget/ChartWidget.d.ts +54 -1
  38. package/dist/widget/ChartWidget.d.ts.map +1 -1
  39. package/dist/widget/DrawingFavoritesStore.d.ts +22 -0
  40. package/dist/widget/DrawingFavoritesStore.d.ts.map +1 -0
  41. package/dist/widget/DrawingTemplateStore.d.ts +29 -0
  42. package/dist/widget/DrawingTemplateStore.d.ts.map +1 -0
  43. package/dist/widget/WidgetAlertsPanel.d.ts +58 -0
  44. package/dist/widget/WidgetAlertsPanel.d.ts.map +1 -0
  45. package/dist/widget/WidgetBracketBar.d.ts +21 -0
  46. package/dist/widget/WidgetBracketBar.d.ts.map +1 -0
  47. package/dist/widget/WidgetDataWindow.d.ts +41 -0
  48. package/dist/widget/WidgetDataWindow.d.ts.map +1 -0
  49. package/dist/widget/WidgetDepthLadder.d.ts +29 -0
  50. package/dist/widget/WidgetDepthLadder.d.ts.map +1 -0
  51. package/dist/widget/WidgetDrawingSidebar.d.ts +6 -0
  52. package/dist/widget/WidgetDrawingSidebar.d.ts.map +1 -1
  53. package/dist/widget/WidgetDrawingStyle.d.ts +36 -0
  54. package/dist/widget/WidgetDrawingStyle.d.ts.map +1 -0
  55. package/dist/widget/WidgetHotkeySheet.d.ts.map +1 -1
  56. package/dist/widget/WidgetIndicatorSettings.d.ts +42 -0
  57. package/dist/widget/WidgetIndicatorSettings.d.ts.map +1 -0
  58. package/dist/widget/WidgetObjectTree.d.ts +59 -0
  59. package/dist/widget/WidgetObjectTree.d.ts.map +1 -0
  60. package/dist/widget/WidgetReplayBar.d.ts +1 -1
  61. package/dist/widget/WidgetSettings.d.ts +1 -0
  62. package/dist/widget/WidgetSettings.d.ts.map +1 -1
  63. package/dist/widget/WidgetSymbolSearch.d.ts +3 -1
  64. package/dist/widget/WidgetSymbolSearch.d.ts.map +1 -1
  65. package/dist/widget/WidgetToolbar.d.ts.map +1 -1
  66. package/dist/widget/icons.d.ts.map +1 -1
  67. package/dist/widget/index.cjs +947 -15
  68. package/dist/widget/index.cjs.map +1 -1
  69. package/dist/widget/index.js +1826 -159
  70. package/dist/widget/index.js.map +1 -1
  71. package/dist/widget/ladderRows.d.ts +21 -0
  72. package/dist/widget/ladderRows.d.ts.map +1 -0
  73. package/dist/widget/types.d.ts +72 -1
  74. package/dist/widget/types.d.ts.map +1 -1
  75. package/dist/widget/widgetConfig.d.ts.map +1 -1
  76. package/dist/widget/widgetShareState.d.ts +26 -0
  77. package/dist/widget/widgetShareState.d.ts.map +1 -0
  78. package/package.json +3 -3
  79. package/dist/DragDropImporter-6QOjnfSj.js.map +0 -1
  80. package/dist/DragDropImporter-CQ3EarQn.cjs +0 -2
  81. package/dist/DragDropImporter-CQ3EarQn.cjs.map +0 -1
@@ -1,4 +1,16 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../DragDropImporter-CQ3EarQn.cjs`);let t=require(`@tradecanvas/commons`);var n=[{label:`1m`,value:`1m`},{label:`5m`,value:`5m`},{label:`15m`,value:`15m`},{label:`1H`,value:`1h`},{label:`4H`,value:`4h`},{label:`1D`,value:`1d`}],r=[{label:`Candlestick`,value:`candlestick`},{label:`Line`,value:`line`},{label:`Area`,value:`area`},{label:`Bar`,value:`bar`},{label:`Heikin-Ashi`,value:`heikinAshi`},{label:`Hollow Candle`,value:`hollowCandle`},{label:`Baseline`,value:`baseline`},{label:`Volume Candles`,value:`volumeCandles`},{label:`Equivolume`,value:`equivolume`},{label:`HLC Area`,value:`hlcArea`},{label:`Step Line`,value:`stepLine`},{label:`Line + Markers`,value:`lineWithMarkers`}],i=[{label:`Lines`,tools:[{label:`Trend Line`,value:`trendLine`},{label:`Ray`,value:`ray`},{label:`Extended Line`,value:`extendedLine`}]},{label:`Horizontal/Vertical`,tools:[{label:`Horizontal Line`,value:`horizontalLine`},{label:`Vertical Line`,value:`verticalLine`}]},{label:`Channels`,tools:[{label:`Parallel Channel`,value:`parallelChannel`},{label:`Regression Channel`,value:`regressionChannel`}]},{label:`Fibonacci`,tools:[{label:`Fib Retracement`,value:`fibRetracement`},{label:`Fib Extension`,value:`fibExtension`}]},{label:`Shapes`,tools:[{label:`Rectangle`,value:`rectangle`},{label:`Ellipse`,value:`ellipse`},{label:`Triangle`,value:`triangle`}]},{label:`Gann & Advanced`,tools:[{label:`Pitchfork`,value:`pitchfork`},{label:`Gann Fan`,value:`gannFan`},{label:`Gann Box`,value:`gannBox`},{label:`Elliott Wave`,value:`elliottWave`}]},{label:`Measure`,tools:[{label:`Price Range`,value:`priceRange`},{label:`Date Range`,value:`dateRange`},{label:`Measure`,value:`measure`}]},{label:`Annotation`,tools:[{label:`Text`,value:`text`},{label:`Arrow`,value:`arrow`}]}],a=[{id:`sma`,name:`SMA`,type:`overlay`},{id:`ema`,name:`EMA`,type:`overlay`},{id:`hma`,name:`Hull MA`,type:`overlay`},{id:`bb`,name:`Bollinger Bands`,type:`overlay`},{id:`vwap`,name:`VWAP`,type:`overlay`},{id:`avwap`,name:`Anchored VWAP`,type:`overlay`},{id:`ichimoku`,name:`Ichimoku Cloud`,type:`overlay`},{id:`psar`,name:`Parabolic SAR`,type:`overlay`},{id:`supertrend`,name:`Supertrend`,type:`overlay`},{id:`keltner`,name:`Keltner Channel`,type:`overlay`},{id:`donchian`,name:`Donchian Channel`,type:`overlay`},{id:`pivots`,name:`Pivot Points`,type:`overlay`},{id:`zigzag`,name:`ZigZag`,type:`overlay`},{id:`lrc`,name:`Linear Regression Channel`,type:`overlay`},{id:`rsi`,name:`RSI`,type:`panel`},{id:`macd`,name:`MACD`,type:`panel`},{id:`stochastic`,name:`Stochastic`,type:`panel`},{id:`atr`,name:`ATR`,type:`panel`},{id:`adx`,name:`ADX`,type:`panel`},{id:`obv`,name:`OBV`,type:`panel`},{id:`williamsR`,name:`Williams %R`,type:`panel`},{id:`cci`,name:`CCI`,type:`panel`},{id:`mfi`,name:`MFI`,type:`panel`},{id:`roc`,name:`ROC`,type:`panel`},{id:`tsi`,name:`TSI`,type:`panel`},{id:`cmf`,name:`CMF`,type:`panel`},{id:`aroon`,name:`Aroon`,type:`panel`},{id:`stddev`,name:`Std Deviation`,type:`panel`},{id:`vroc`,name:`Volume ROC`,type:`panel`},{id:`ad`,name:`Acc/Dist`,type:`panel`},{id:`ao`,name:`Awesome Oscillator`,type:`panel`},{id:`chaikinOsc`,name:`Chaikin Oscillator`,type:`panel`},{id:`volumeProfile`,name:`Volume Profile`,type:`panel`}],o=[`sma`,`ema`,`bb`,`rsi`,`macd`,`stochastic`,`vwap`,`atr`,`obv`,`ichimoku`],s=[`BTCUSDT`,`ETHUSDT`,`SOLUSDT`,`BNBUSDT`],c={candleUpColor:`#26A69A`,candleDownColor:`#EF5350`,candleUpWick:`#26A69A`,candleDownWick:`#EF5350`,backgroundColor:`#131722`,gridColor:`#1E222D`,gridVisible:!0,volumeVisible:!0,volumeProfileVisible:!1,legendVisible:!0,barCountdown:!0,logScale:!1,autoScale:!0,crosshairMode:`magnet`,numberLocale:`en-US`},l=`/* === TradeCanvas Widget — Premium Styles === */
1
+ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../DragDropImporter-DeXlngof.cjs`);let t=require(`@tradecanvas/commons`);function n(e,n,r={}){if(e.length===0)return[];let i=r.weekStartsOn??1,a=[],o=null,s=NaN;for(let r of e){let e=(0,t.timeframeBucketStart)(r.time,n,i);o===null||e!==s?(o!==null&&a.push(o),o={time:e,open:r.open,high:r.high,low:r.low,close:r.close,volume:r.volume},s=e):o={time:o.time,open:o.open,high:Math.max(o.high,r.high),low:Math.min(o.low,r.low),close:r.close,volume:o.volume+r.volume}}return o!==null&&a.push(o),a}function r(e){if(e.length<2)return 0;let t=[];for(let n=1;n<e.length;n++){let r=e[n].time-e[n-1].time;r>0&&t.push(r)}return t.length===0?0:(t.sort((e,t)=>e-t),t[Math.floor(t.length/2)])}var i=[{label:`1m`,value:`1m`},{label:`5m`,value:`5m`},{label:`15m`,value:`15m`},{label:`1H`,value:`1h`},{label:`4H`,value:`4h`},{label:`1D`,value:`1d`}],a=[{label:`Candlestick`,value:`candlestick`},{label:`Line`,value:`line`},{label:`Area`,value:`area`},{label:`Bar`,value:`bar`},{label:`Heikin-Ashi`,value:`heikinAshi`},{label:`Hollow Candle`,value:`hollowCandle`},{label:`Baseline`,value:`baseline`},{label:`Volume Candles`,value:`volumeCandles`},{label:`Equivolume`,value:`equivolume`},{label:`HLC Area`,value:`hlcArea`},{label:`Step Line`,value:`stepLine`},{label:`Line + Markers`,value:`lineWithMarkers`}],o=[{label:`Lines`,tools:[{label:`Trend Line`,value:`trendLine`},{label:`Ray`,value:`ray`},{label:`Extended Line`,value:`extendedLine`}]},{label:`Horizontal/Vertical`,tools:[{label:`Horizontal Line`,value:`horizontalLine`},{label:`Vertical Line`,value:`verticalLine`}]},{label:`Channels`,tools:[{label:`Parallel Channel`,value:`parallelChannel`},{label:`Regression Channel`,value:`regressionChannel`}]},{label:`Fibonacci`,tools:[{label:`Fib Retracement`,value:`fibRetracement`},{label:`Fib Extension`,value:`fibExtension`}]},{label:`Shapes`,tools:[{label:`Rectangle`,value:`rectangle`},{label:`Ellipse`,value:`ellipse`},{label:`Triangle`,value:`triangle`}]},{label:`Gann & Advanced`,tools:[{label:`Pitchfork`,value:`pitchfork`},{label:`Gann Fan`,value:`gannFan`},{label:`Gann Box`,value:`gannBox`},{label:`Elliott Wave`,value:`elliottWave`}]},{label:`Measure`,tools:[{label:`Price Range`,value:`priceRange`},{label:`Date Range`,value:`dateRange`},{label:`Measure`,value:`measure`}]},{label:`Annotation`,tools:[{label:`Text`,value:`text`},{label:`Arrow`,value:`arrow`}]}],s=[{id:`sma`,name:`SMA`,type:`overlay`},{id:`ema`,name:`EMA`,type:`overlay`},{id:`hma`,name:`Hull MA`,type:`overlay`},{id:`mtfma`,name:`MTF Moving Average`,type:`overlay`},{id:`bb`,name:`Bollinger Bands`,type:`overlay`},{id:`vwap`,name:`VWAP`,type:`overlay`},{id:`avwap`,name:`Anchored VWAP`,type:`overlay`},{id:`svwap`,name:`Session VWAP`,type:`overlay`},{id:`ichimoku`,name:`Ichimoku Cloud`,type:`overlay`},{id:`psar`,name:`Parabolic SAR`,type:`overlay`},{id:`supertrend`,name:`Supertrend`,type:`overlay`},{id:`keltner`,name:`Keltner Channel`,type:`overlay`},{id:`donchian`,name:`Donchian Channel`,type:`overlay`},{id:`pivots`,name:`Pivot Points`,type:`overlay`},{id:`zigzag`,name:`ZigZag`,type:`overlay`},{id:`lrc`,name:`Linear Regression Channel`,type:`overlay`},{id:`chandelier`,name:`Chandelier Exit`,type:`overlay`},{id:`alligator`,name:`Alligator`,type:`overlay`},{id:`rsi`,name:`RSI`,type:`panel`},{id:`macd`,name:`MACD`,type:`panel`},{id:`stochastic`,name:`Stochastic`,type:`panel`},{id:`atr`,name:`ATR`,type:`panel`},{id:`adx`,name:`ADX`,type:`panel`},{id:`obv`,name:`OBV`,type:`panel`},{id:`williamsR`,name:`Williams %R`,type:`panel`},{id:`cci`,name:`CCI`,type:`panel`},{id:`mfi`,name:`MFI`,type:`panel`},{id:`roc`,name:`ROC`,type:`panel`},{id:`tsi`,name:`TSI`,type:`panel`},{id:`cmf`,name:`CMF`,type:`panel`},{id:`aroon`,name:`Aroon`,type:`panel`},{id:`stddev`,name:`Std Deviation`,type:`panel`},{id:`vroc`,name:`Volume ROC`,type:`panel`},{id:`ad`,name:`Acc/Dist`,type:`panel`},{id:`ao`,name:`Awesome Oscillator`,type:`panel`},{id:`chaikinOsc`,name:`Chaikin Oscillator`,type:`panel`},{id:`voldelta`,name:`Volume Delta`,type:`panel`},{id:`vortex`,name:`Vortex Indicator`,type:`panel`},{id:`chop`,name:`Choppiness Index`,type:`panel`},{id:`uo`,name:`Ultimate Oscillator`,type:`panel`},{id:`fi`,name:`Force Index`,type:`panel`},{id:`crsi`,name:`Connors RSI`,type:`panel`},{id:`coppock`,name:`Coppock Curve`,type:`panel`},{id:`kst`,name:`Know Sure Thing`,type:`panel`},{id:`elderray`,name:`Elder Ray`,type:`panel`},{id:`stc`,name:`Schaff Trend Cycle`,type:`panel`},{id:`kvo`,name:`Klinger Oscillator`,type:`panel`},{id:`fisher`,name:`Fisher Transform`,type:`panel`},{id:`dpo`,name:`Detrended Price Osc`,type:`panel`},{id:`bop`,name:`Balance of Power`,type:`panel`},{id:`massindex`,name:`Mass Index`,type:`panel`},{id:`cmo`,name:`Chande Momentum`,type:`panel`},{id:`trix`,name:`TRIX`,type:`panel`},{id:`emv`,name:`Ease of Movement`,type:`panel`},{id:`pvt`,name:`Price Volume Trend`,type:`panel`},{id:`wad`,name:`Williams A/D`,type:`panel`},{id:`chaikinvol`,name:`Chaikin Volatility`,type:`panel`},{id:`rvi`,name:`Relative Vigor Index`,type:`panel`},{id:`stochrsi`,name:`Stochastic RSI`,type:`panel`},{id:`ppo`,name:`Percentage Price Oscillator`,type:`panel`},{id:`ac`,name:`Accelerator Oscillator`,type:`panel`},{id:`rmi`,name:`Relative Momentum Index`,type:`panel`},{id:`disparity`,name:`Disparity Index`,type:`panel`},{id:`qstick`,name:`Qstick`,type:`panel`},{id:`pgo`,name:`Pretty Good Oscillator`,type:`panel`},{id:`volumeProfile`,name:`Volume Profile`,type:`panel`}],c=[`sma`,`ema`,`bb`,`rsi`,`macd`,`stochastic`,`vwap`,`atr`,`obv`,`ichimoku`],l=[`BTCUSDT`,`ETHUSDT`,`SOLUSDT`,`BNBUSDT`],u={candleUpColor:`#26A69A`,candleDownColor:`#EF5350`,candleUpWick:`#26A69A`,candleDownWick:`#EF5350`,backgroundColor:`#131722`,gridColor:`#1E222D`,gridVisible:!0,volumeVisible:!0,volumeProfileVisible:!1,marketProfileVisible:!1,marketProfileSplit:!1,marketProfileLetters:!1,marketProfileBuckets:48,marketProfileOpacity:.32,depthHeatmapVisible:!1,depthHeatmapOpacity:.7,sessionShadingVisible:!1,pivotMarkersVisible:!1,pivotStrength:5,pivotStructureLabels:!1,periodLevelsVisible:!1,periodLevelsPeriod:`day`,legendVisible:!0,barCountdown:!0,logScale:!1,scaleMode:`regular`,autoScale:!0,crosshairMode:`magnet`,numberLocale:`en-US`,timezone:`local`},d=`/* === TradeCanvas Widget — Premium Styles === */
2
+
3
+ /*
4
+ * The HTML \`hidden\` attribute only sets \`display: none\` via the UA stylesheet,
5
+ * which any author \`display\` rule (e.g. \`.tcw-alerts-panel { display: flex }\`)
6
+ * silently overrides — leaving panels stuck open when JS sets \`el.hidden = true\`.
7
+ * Force \`hidden\` to win for every namespaced widget element. Scoped to \`tcw-\`
8
+ * so it never touches the host page.
9
+ */
10
+ [class^="tcw-"][hidden],
11
+ [class*=" tcw-"][hidden] {
12
+ display: none !important;
13
+ }
2
14
 
3
15
  .tcw-root {
4
16
  display: flex;
@@ -535,6 +547,36 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=requi
535
547
  font-weight: 600;
536
548
  }
537
549
 
550
+ /* Pinned (favorited) flyout item — a star marker on the right. */
551
+ .tcw-flyout-item.tcw-flyout-faved::after {
552
+ content: '★';
553
+ float: right;
554
+ color: var(--tcw-accent);
555
+ font-size: 11px;
556
+ line-height: 1.4;
557
+ }
558
+
559
+ /* Favorites strip — pinned drawing tools above the tool groups. */
560
+ .tcw-sidebar-favorites {
561
+ display: flex;
562
+ flex-direction: column;
563
+ gap: 2px;
564
+ }
565
+ .tcw-sidebar-favorites .tcw-sidebar-btn {
566
+ position: relative;
567
+ }
568
+ .tcw-sidebar-favorites .tcw-sidebar-btn::before {
569
+ content: '';
570
+ position: absolute;
571
+ top: 3px;
572
+ right: 3px;
573
+ width: 4px;
574
+ height: 4px;
575
+ border-radius: 50%;
576
+ background: var(--tcw-accent);
577
+ opacity: 0.7;
578
+ }
579
+
538
580
  /* === Modal === */
539
581
 
540
582
  .tcw-modal-backdrop {
@@ -1407,8 +1449,8 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=requi
1407
1449
 
1408
1450
  @media (max-width: 768px) {
1409
1451
  .tcw-toolbar {
1410
- padding: 0 6px;
1411
- height: 40px;
1452
+ padding: 0 4px;
1453
+ height: 44px; /* Apple HIG minimum touch target */
1412
1454
  }
1413
1455
  .tcw-toolbar-sep {
1414
1456
  display: none;
@@ -1416,20 +1458,910 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=requi
1416
1458
  .tcw-indicator-chips {
1417
1459
  display: none;
1418
1460
  }
1461
+ .tcw-btn,
1462
+ .tcw-dropdown-trigger {
1463
+ padding: 10px 12px; /* fatter tap target */
1464
+ font-size: 13px;
1465
+ }
1466
+ .tcw-btn-icon {
1467
+ width: 40px;
1468
+ height: 40px;
1469
+ }
1419
1470
  .tcw-sidebar {
1420
- width: 36px;
1471
+ width: 44px;
1421
1472
  }
1422
1473
  .tcw-sidebar-btn {
1423
- width: 28px;
1424
- height: 28px;
1474
+ width: 40px;
1475
+ height: 40px;
1425
1476
  }
1426
- .tcw-modal {
1477
+ .tcw-modal,
1478
+ .tcw-cmd-palette {
1427
1479
  width: 94vw;
1428
1480
  border-radius: var(--tcw-radius-lg);
1429
1481
  }
1482
+
1483
+ /* Hide the right-side watchlist on tablets too — already declared but
1484
+ * grouped here for clarity. */
1485
+ .tcw-watchlist {
1486
+ display: none;
1487
+ }
1488
+
1489
+ /* Replay scrubber compact mode */
1490
+ .tcw-replay-scrubber {
1491
+ width: 120px;
1492
+ }
1493
+ .tcw-replay-progress {
1494
+ display: none;
1495
+ }
1496
+ }
1497
+
1498
+ /* === Mobile bottom-sheet pattern ===
1499
+ * On phones, swap floating-centered modals for full-width sheets that slide
1500
+ * up from the bottom. Bigger hit targets, no awkward off-screen clipping,
1501
+ * matches how every modern iOS/Android app handles overflow UI.
1502
+ */
1503
+ @media (max-width: 640px) {
1504
+ .tcw-modal,
1430
1505
  .tcw-cmd-palette {
1431
- width: 94vw;
1432
- border-radius: var(--tcw-radius-lg);
1506
+ top: auto;
1507
+ bottom: 0;
1508
+ left: 0;
1509
+ right: 0;
1510
+ transform: none;
1511
+ width: 100vw;
1512
+ max-width: 100vw;
1513
+ max-height: 92vh;
1514
+ border-radius: var(--tcw-radius-xl) var(--tcw-radius-xl) 0 0;
1515
+ border-bottom: none;
1516
+ /* Grab handle */
1517
+ padding-top: 8px;
1518
+ }
1519
+
1520
+ /* Visual "grab handle" affordance — a short pill at the top of every sheet */
1521
+ .tcw-modal::before,
1522
+ .tcw-cmd-palette::before {
1523
+ content: '';
1524
+ display: block;
1525
+ width: 36px;
1526
+ height: 4px;
1527
+ border-radius: 2px;
1528
+ background: var(--tcw-border-strong);
1529
+ margin: 0 auto 8px;
1530
+ opacity: 0.7;
1531
+ }
1532
+
1533
+ /* Reuse the existing modal-in animation but slide from below instead of
1534
+ * popping from center, so the entrance reads as a sheet, not a dialog. */
1535
+ @keyframes tcw-modal-in {
1536
+ from { opacity: 0; transform: translateY(20px); }
1537
+ to { opacity: 1; transform: translateY(0); }
1538
+ }
1539
+
1540
+ .tcw-modal,
1541
+ .tcw-cmd-palette {
1542
+ animation: tcw-modal-in var(--tcw-dur-slow) var(--tcw-ease-out);
1543
+ }
1544
+
1545
+ /* Safe-area-aware footer padding for iPhone notch / home indicator */
1546
+ .tcw-modal-footer,
1547
+ .tcw-cmd-footer {
1548
+ padding-bottom: max(14px, env(safe-area-inset-bottom));
1549
+ }
1550
+
1551
+ /* Larger tap targets inside sheets */
1552
+ .tcw-modal-tab {
1553
+ padding: 14px 16px;
1554
+ }
1555
+ .tcw-cmd-item {
1556
+ padding: 12px 14px;
1557
+ font-size: 14px;
1558
+ }
1559
+ .tcw-dropdown-item {
1560
+ padding: 12px 12px;
1561
+ font-size: 14px;
1562
+ }
1563
+
1564
+ /* Hotkey sheet — single column on phones */
1565
+ .tcw-hotkey-grid {
1566
+ grid-template-columns: 1fr;
1567
+ }
1568
+ }
1569
+
1570
+ /* === Price alerts panel === */
1571
+
1572
+ .tcw-alerts-panel {
1573
+ position: absolute;
1574
+ top: 50px;
1575
+ right: 12px;
1576
+ z-index: 40;
1577
+ width: 300px;
1578
+ max-width: calc(100vw - 24px);
1579
+ display: flex;
1580
+ flex-direction: column;
1581
+ background: var(--tcw-bg-elevated);
1582
+ border: 1px solid var(--tcw-border-strong);
1583
+ border-radius: var(--tcw-radius-lg);
1584
+ box-shadow: var(--tcw-shadow-lg);
1585
+ overflow: hidden;
1586
+ animation: tcw-alerts-in var(--tcw-dur, 160ms) var(--tcw-ease, ease) both;
1587
+ }
1588
+
1589
+ @keyframes tcw-alerts-in {
1590
+ from { opacity: 0; transform: translateY(-6px) scale(0.98); }
1591
+ to { opacity: 1; transform: none; }
1592
+ }
1593
+
1594
+ .tcw-alerts-header {
1595
+ display: flex;
1596
+ align-items: center;
1597
+ justify-content: space-between;
1598
+ padding: 10px 12px;
1599
+ font-weight: 600;
1600
+ font-size: 13px;
1601
+ color: var(--tcw-text);
1602
+ border-bottom: 1px solid var(--tcw-border);
1603
+ }
1604
+
1605
+ .tcw-alerts-close {
1606
+ display: inline-flex;
1607
+ align-items: center;
1608
+ justify-content: center;
1609
+ width: 26px;
1610
+ height: 26px;
1611
+ border: none;
1612
+ background: transparent;
1613
+ color: var(--tcw-text-muted);
1614
+ border-radius: var(--tcw-radius-sm);
1615
+ cursor: pointer;
1616
+ }
1617
+ .tcw-alerts-close:hover {
1618
+ background: var(--tcw-bg-surface);
1619
+ color: var(--tcw-text);
1620
+ }
1621
+
1622
+ .tcw-alerts-form {
1623
+ display: grid;
1624
+ grid-template-columns: 1fr 1fr;
1625
+ gap: 8px;
1626
+ padding: 12px;
1627
+ border-bottom: 1px solid var(--tcw-border);
1628
+ }
1629
+
1630
+ .tcw-alerts-form input,
1631
+ .tcw-alerts-form select {
1632
+ width: 100%;
1633
+ min-width: 0;
1634
+ box-sizing: border-box;
1635
+ height: 32px;
1636
+ padding: 0 8px;
1637
+ font-size: 12px;
1638
+ color: var(--tcw-text);
1639
+ background: var(--tcw-bg-surface);
1640
+ border: 1px solid var(--tcw-border);
1641
+ border-radius: var(--tcw-radius-sm);
1642
+ outline: none;
1643
+ }
1644
+ .tcw-alerts-form input:focus,
1645
+ .tcw-alerts-form select:focus {
1646
+ border-color: var(--tcw-accent);
1647
+ box-shadow: 0 0 0 2px var(--tcw-accent-soft);
1648
+ }
1649
+ .tcw-alerts-message,
1650
+ .tcw-alerts-source {
1651
+ grid-column: 1 / -1;
1652
+ }
1653
+
1654
+ .tcw-alerts-add {
1655
+ grid-column: 1 / -1;
1656
+ display: inline-flex;
1657
+ align-items: center;
1658
+ justify-content: center;
1659
+ gap: 6px;
1660
+ height: 34px;
1661
+ font-size: 12px;
1662
+ font-weight: 600;
1663
+ color: #fff;
1664
+ background: var(--tcw-accent);
1665
+ border: none;
1666
+ border-radius: var(--tcw-radius-sm);
1667
+ cursor: pointer;
1668
+ }
1669
+ .tcw-alerts-add:hover {
1670
+ background: var(--tcw-accent-hover);
1671
+ }
1672
+
1673
+ .tcw-alerts-list {
1674
+ max-height: 260px;
1675
+ overflow-y: auto;
1676
+ padding: 6px;
1677
+ }
1678
+
1679
+ .tcw-alerts-empty {
1680
+ padding: 18px 12px;
1681
+ text-align: center;
1682
+ font-size: 12px;
1683
+ color: var(--tcw-text-muted);
1684
+ line-height: 1.5;
1685
+ }
1686
+
1687
+ .tcw-alerts-row {
1688
+ display: flex;
1689
+ align-items: center;
1690
+ justify-content: space-between;
1691
+ gap: 8px;
1692
+ padding: 8px 8px;
1693
+ border-radius: var(--tcw-radius-sm);
1694
+ }
1695
+ .tcw-alerts-row:hover {
1696
+ background: var(--tcw-bg-surface);
1697
+ }
1698
+ .tcw-alerts-triggered {
1699
+ background: var(--tcw-accent-soft);
1700
+ }
1701
+
1702
+ .tcw-alerts-info {
1703
+ min-width: 0;
1704
+ }
1705
+ .tcw-alerts-row-main {
1706
+ display: flex;
1707
+ align-items: center;
1708
+ gap: 8px;
1709
+ font-size: 12px;
1710
+ font-weight: 600;
1711
+ color: var(--tcw-text);
1712
+ font-variant-numeric: tabular-nums;
1713
+ }
1714
+ .tcw-alerts-row-note {
1715
+ margin-top: 2px;
1716
+ font-size: 11px;
1717
+ color: var(--tcw-text-muted);
1718
+ overflow: hidden;
1719
+ text-overflow: ellipsis;
1720
+ white-space: nowrap;
1721
+ }
1722
+ .tcw-alerts-badge {
1723
+ font-size: 9px;
1724
+ font-weight: 700;
1725
+ text-transform: uppercase;
1726
+ letter-spacing: 0.04em;
1727
+ padding: 2px 5px;
1728
+ border-radius: 999px;
1729
+ color: var(--tcw-accent);
1730
+ background: var(--tcw-accent-soft);
1731
+ }
1732
+
1733
+ .tcw-alerts-del {
1734
+ flex-shrink: 0;
1735
+ display: inline-flex;
1736
+ align-items: center;
1737
+ justify-content: center;
1738
+ width: 28px;
1739
+ height: 28px;
1740
+ border: none;
1741
+ background: transparent;
1742
+ color: var(--tcw-text-muted);
1743
+ border-radius: var(--tcw-radius-sm);
1744
+ cursor: pointer;
1745
+ }
1746
+ .tcw-alerts-del:hover {
1747
+ background: var(--tcw-red-soft);
1748
+ color: var(--tcw-red);
1749
+ }
1750
+
1751
+ @media (max-width: 640px) {
1752
+ .tcw-alerts-panel {
1753
+ top: auto;
1754
+ bottom: 0;
1755
+ left: 0;
1756
+ right: 0;
1757
+ width: 100vw;
1758
+ max-width: 100vw;
1759
+ border-radius: var(--tcw-radius-xl) var(--tcw-radius-xl) 0 0;
1760
+ }
1761
+ .tcw-alerts-list {
1762
+ max-height: 40vh;
1763
+ padding-bottom: max(8px, env(safe-area-inset-bottom));
1764
+ }
1765
+ }
1766
+
1767
+ /* === Data Window === */
1768
+
1769
+ .tcw-datawin {
1770
+ position: absolute;
1771
+ top: 50px;
1772
+ right: 12px;
1773
+ z-index: 38;
1774
+ width: 200px;
1775
+ display: flex;
1776
+ flex-direction: column;
1777
+ background: var(--tcw-bg-elevated);
1778
+ border: 1px solid var(--tcw-border-strong);
1779
+ border-radius: var(--tcw-radius-lg);
1780
+ box-shadow: var(--tcw-shadow-lg);
1781
+ overflow: hidden;
1782
+ animation: tcw-alerts-in var(--tcw-dur, 160ms) var(--tcw-ease, ease) both;
1783
+ }
1784
+ .tcw-datawin-header {
1785
+ display: flex;
1786
+ align-items: center;
1787
+ justify-content: space-between;
1788
+ padding: 9px 12px;
1789
+ font-size: 12px;
1790
+ font-weight: 600;
1791
+ color: var(--tcw-text);
1792
+ border-bottom: 1px solid var(--tcw-border);
1793
+ }
1794
+ .tcw-datawin-close {
1795
+ display: inline-flex;
1796
+ align-items: center;
1797
+ justify-content: center;
1798
+ width: 24px;
1799
+ height: 24px;
1800
+ border: none;
1801
+ background: transparent;
1802
+ color: var(--tcw-text-muted);
1803
+ border-radius: var(--tcw-radius-sm);
1804
+ cursor: pointer;
1805
+ }
1806
+ .tcw-datawin-close:hover { background: var(--tcw-bg-surface); color: var(--tcw-text); }
1807
+ .tcw-datawin-body { padding: 6px 4px; max-height: 360px; overflow-y: auto; }
1808
+ .tcw-datawin-empty { padding: 14px; text-align: center; font-size: 12px; color: var(--tcw-text-muted); }
1809
+ .tcw-datawin-row {
1810
+ display: flex;
1811
+ align-items: center;
1812
+ justify-content: space-between;
1813
+ gap: 10px;
1814
+ padding: 3px 8px;
1815
+ font-size: 12px;
1816
+ }
1817
+ .tcw-datawin-label { color: var(--tcw-text-muted); }
1818
+ .tcw-datawin-value { color: var(--tcw-text); font-variant-numeric: tabular-nums; font-weight: 600; }
1819
+ .tcw-datawin-value.tcw-up { color: var(--tcw-green); }
1820
+ .tcw-datawin-value.tcw-down { color: var(--tcw-red); }
1821
+ .tcw-datawin-sub {
1822
+ margin: 6px 8px 2px;
1823
+ font-size: 10px;
1824
+ font-weight: 700;
1825
+ text-transform: uppercase;
1826
+ letter-spacing: 0.04em;
1827
+ color: var(--tcw-text-muted);
1828
+ border-top: 1px solid var(--tcw-border);
1829
+ padding-top: 6px;
1830
+ }
1831
+
1832
+ @media (max-width: 640px) {
1833
+ .tcw-datawin { top: auto; bottom: 0; left: 0; right: 0; width: 100vw; border-radius: var(--tcw-radius-xl) var(--tcw-radius-xl) 0 0; }
1834
+ }
1835
+
1836
+ /* === Depth-of-market ladder === */
1837
+
1838
+ .tcw-ladder {
1839
+ position: absolute;
1840
+ top: 50px;
1841
+ right: 12px;
1842
+ z-index: 41;
1843
+ width: 240px;
1844
+ display: flex;
1845
+ flex-direction: column;
1846
+ background: var(--tcw-bg-elevated);
1847
+ border: 1px solid var(--tcw-border-strong);
1848
+ border-radius: var(--tcw-radius-lg);
1849
+ box-shadow: var(--tcw-shadow-lg);
1850
+ overflow: hidden;
1851
+ animation: tcw-alerts-in var(--tcw-dur, 160ms) var(--tcw-ease, ease) both;
1852
+ }
1853
+ .tcw-ladder-header {
1854
+ display: flex;
1855
+ align-items: center;
1856
+ justify-content: space-between;
1857
+ padding: 10px 12px;
1858
+ font-size: 13px;
1859
+ font-weight: 600;
1860
+ color: var(--tcw-text);
1861
+ border-bottom: 1px solid var(--tcw-border);
1862
+ }
1863
+ .tcw-ladder-close {
1864
+ display: inline-flex;
1865
+ align-items: center;
1866
+ justify-content: center;
1867
+ width: 26px;
1868
+ height: 26px;
1869
+ border: none;
1870
+ background: transparent;
1871
+ color: var(--tcw-text-muted);
1872
+ border-radius: var(--tcw-radius-sm);
1873
+ cursor: pointer;
1874
+ }
1875
+ .tcw-ladder-close:hover { background: var(--tcw-bg-surface); color: var(--tcw-text); }
1876
+ .tcw-ladder-cols {
1877
+ display: grid;
1878
+ grid-template-columns: 1fr 1fr 1fr;
1879
+ padding: 4px 0;
1880
+ font-size: 10px;
1881
+ font-weight: 700;
1882
+ text-transform: uppercase;
1883
+ letter-spacing: 0.04em;
1884
+ color: var(--tcw-text-muted);
1885
+ border-bottom: 1px solid var(--tcw-border);
1886
+ }
1887
+ .tcw-ladder-cols span { text-align: center; }
1888
+ .tcw-ladder-body { max-height: 360px; overflow-y: auto; }
1889
+ .tcw-ladder-empty { padding: 18px; text-align: center; font-size: 12px; color: var(--tcw-text-muted); }
1890
+
1891
+ .tcw-ladder-row {
1892
+ display: grid;
1893
+ grid-template-columns: 1fr 1fr 1fr;
1894
+ height: 22px;
1895
+ font-variant-numeric: tabular-nums;
1896
+ }
1897
+ .tcw-ladder-cell {
1898
+ position: relative;
1899
+ display: flex;
1900
+ align-items: center;
1901
+ border: none;
1902
+ background: transparent;
1903
+ font-size: 11px;
1904
+ cursor: pointer;
1905
+ font-variant-numeric: tabular-nums;
1906
+ overflow: hidden;
1907
+ }
1908
+ .tcw-ladder-cell:disabled { cursor: default; }
1909
+ /* Depth bar grows from the centre column outward. */
1910
+ .tcw-ladder-cell::before {
1911
+ content: '';
1912
+ position: absolute;
1913
+ top: 1px; bottom: 1px;
1914
+ width: var(--w, 0%);
1915
+ }
1916
+ .tcw-ladder-bid { justify-content: flex-end; padding-right: 8px; color: var(--tcw-green); }
1917
+ .tcw-ladder-bid::before { right: 0; background: var(--tcw-green-soft); }
1918
+ .tcw-ladder-bid span, .tcw-ladder-bid { position: relative; }
1919
+ .tcw-ladder-ask { justify-content: flex-start; padding-left: 8px; color: var(--tcw-red); }
1920
+ .tcw-ladder-ask::before { left: 0; background: var(--tcw-red-soft); }
1921
+ .tcw-ladder-cell:not(:disabled):hover::before { opacity: 0.7; filter: brightness(1.4); }
1922
+ .tcw-ladder-cell > * { position: relative; }
1923
+ .tcw-ladder-price {
1924
+ display: flex;
1925
+ align-items: center;
1926
+ justify-content: center;
1927
+ font-size: 11px;
1928
+ font-weight: 600;
1929
+ color: var(--tcw-text-dim);
1930
+ border-left: 1px solid var(--tcw-border);
1931
+ border-right: 1px solid var(--tcw-border);
1932
+ }
1933
+ .tcw-ladder-price.tcw-ask { color: var(--tcw-red); }
1934
+ .tcw-ladder-price.tcw-bid { color: var(--tcw-green); }
1935
+
1936
+ @media (max-width: 640px) {
1937
+ .tcw-ladder { top: auto; bottom: 0; left: 0; right: 0; width: 100vw; border-radius: var(--tcw-radius-xl) var(--tcw-radius-xl) 0 0; }
1938
+ .tcw-ladder-body { max-height: 45vh; padding-bottom: max(0px, env(safe-area-inset-bottom)); }
1939
+ }
1940
+
1941
+ /* === Bracket order placement === */
1942
+
1943
+ .tcw-btn-long:hover { color: var(--tcw-green) !important; }
1944
+ .tcw-btn-short:hover { color: var(--tcw-red) !important; }
1945
+
1946
+ .tcw-bracket-bar {
1947
+ position: absolute;
1948
+ top: 52px;
1949
+ left: 50%;
1950
+ transform: translateX(-50%);
1951
+ z-index: 45;
1952
+ display: flex;
1953
+ align-items: center;
1954
+ gap: 10px;
1955
+ padding: 7px 8px 7px 14px;
1956
+ background: var(--tcw-bg-elevated);
1957
+ border: 1px solid var(--tcw-border-strong);
1958
+ border-radius: 999px;
1959
+ box-shadow: var(--tcw-shadow-lg);
1960
+ animation: tcw-alerts-in var(--tcw-dur, 160ms) var(--tcw-ease, ease) both;
1961
+ }
1962
+ .tcw-bracket-label {
1963
+ font-size: 12px;
1964
+ font-weight: 700;
1965
+ }
1966
+ .tcw-bracket-label[data-side='buy'] { color: var(--tcw-green); }
1967
+ .tcw-bracket-label[data-side='sell'] { color: var(--tcw-red); }
1968
+ .tcw-bracket-hint {
1969
+ font-size: 11px;
1970
+ color: var(--tcw-text-muted);
1971
+ }
1972
+ .tcw-bracket-cancel, .tcw-bracket-confirm {
1973
+ display: inline-flex;
1974
+ align-items: center;
1975
+ gap: 5px;
1976
+ height: 30px;
1977
+ padding: 0 12px;
1978
+ font-size: 12px;
1979
+ font-weight: 600;
1980
+ border: none;
1981
+ border-radius: 999px;
1982
+ cursor: pointer;
1983
+ }
1984
+ .tcw-bracket-cancel {
1985
+ color: var(--tcw-text-dim);
1986
+ background: var(--tcw-bg-surface);
1987
+ }
1988
+ .tcw-bracket-cancel:hover { color: var(--tcw-text); }
1989
+ .tcw-bracket-confirm {
1990
+ color: #fff;
1991
+ background: var(--tcw-accent);
1992
+ }
1993
+ .tcw-bracket-confirm:hover { background: var(--tcw-accent-hover); }
1994
+
1995
+ @media (max-width: 640px) {
1996
+ .tcw-bracket-bar { width: calc(100vw - 24px); justify-content: space-between; }
1997
+ .tcw-bracket-hint { display: none; }
1998
+ }
1999
+
2000
+ /* === Drawing style + templates popover === */
2001
+
2002
+ .tcw-style-panel {
2003
+ position: absolute;
2004
+ bottom: 12px;
2005
+ left: 52px;
2006
+ z-index: 40;
2007
+ width: 220px;
2008
+ display: flex;
2009
+ flex-direction: column;
2010
+ gap: 8px;
2011
+ padding: 12px;
2012
+ background: var(--tcw-bg-elevated);
2013
+ border: 1px solid var(--tcw-border-strong);
2014
+ border-radius: var(--tcw-radius-lg);
2015
+ box-shadow: var(--tcw-shadow-lg);
2016
+ animation: tcw-alerts-in var(--tcw-dur, 160ms) var(--tcw-ease, ease) both;
2017
+ }
2018
+ .tcw-style-header {
2019
+ display: flex;
2020
+ align-items: center;
2021
+ justify-content: space-between;
2022
+ font-size: 12px;
2023
+ font-weight: 600;
2024
+ color: var(--tcw-text);
2025
+ }
2026
+ .tcw-style-close {
2027
+ display: inline-flex;
2028
+ align-items: center;
2029
+ justify-content: center;
2030
+ width: 24px;
2031
+ height: 24px;
2032
+ border: none;
2033
+ background: transparent;
2034
+ color: var(--tcw-text-muted);
2035
+ border-radius: var(--tcw-radius-sm);
2036
+ cursor: pointer;
2037
+ }
2038
+ .tcw-style-close:hover { background: var(--tcw-bg-surface); color: var(--tcw-text); }
2039
+
2040
+ .tcw-style-row { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
2041
+ .tcw-style-swatch {
2042
+ width: 18px;
2043
+ height: 18px;
2044
+ border-radius: 50%;
2045
+ border: 1px solid var(--tcw-border-strong);
2046
+ cursor: pointer;
2047
+ padding: 0;
2048
+ }
2049
+ .tcw-style-swatch.tcw-on { outline: 2px solid var(--tcw-accent); outline-offset: 1px; }
2050
+ .tcw-style-picker {
2051
+ width: 22px;
2052
+ height: 22px;
2053
+ padding: 0;
2054
+ border: 1px solid var(--tcw-border);
2055
+ border-radius: var(--tcw-radius-sm);
2056
+ background: transparent;
2057
+ cursor: pointer;
2058
+ }
2059
+ .tcw-style-width, .tcw-style-dash {
2060
+ flex: 1;
2061
+ min-width: 0;
2062
+ height: 26px;
2063
+ display: flex;
2064
+ align-items: center;
2065
+ justify-content: center;
2066
+ background: var(--tcw-bg-surface);
2067
+ border: 1px solid var(--tcw-border);
2068
+ border-radius: var(--tcw-radius-sm);
2069
+ color: var(--tcw-text-dim);
2070
+ cursor: pointer;
2071
+ font-size: 11px;
2072
+ }
2073
+ .tcw-style-width span { width: 16px; background: currentColor; border-radius: 2px; }
2074
+ .tcw-style-width.tcw-on, .tcw-style-dash.tcw-on {
2075
+ border-color: var(--tcw-accent);
2076
+ color: var(--tcw-accent);
2077
+ }
2078
+
2079
+ .tcw-style-subhead {
2080
+ font-size: 10px;
2081
+ font-weight: 700;
2082
+ text-transform: uppercase;
2083
+ letter-spacing: 0.05em;
2084
+ color: var(--tcw-text-muted);
2085
+ margin-top: 2px;
2086
+ }
2087
+ .tcw-style-save { display: flex; gap: 6px; }
2088
+ .tcw-style-name {
2089
+ flex: 1;
2090
+ min-width: 0;
2091
+ height: 28px;
2092
+ padding: 0 8px;
2093
+ font-size: 12px;
2094
+ color: var(--tcw-text);
2095
+ background: var(--tcw-bg-surface);
2096
+ border: 1px solid var(--tcw-border);
2097
+ border-radius: var(--tcw-radius-sm);
2098
+ outline: none;
2099
+ }
2100
+ .tcw-style-name:focus { border-color: var(--tcw-accent); }
2101
+ .tcw-style-savebtn {
2102
+ display: inline-flex;
2103
+ align-items: center;
2104
+ gap: 4px;
2105
+ padding: 0 10px;
2106
+ height: 28px;
2107
+ font-size: 12px;
2108
+ font-weight: 600;
2109
+ color: #fff;
2110
+ background: var(--tcw-accent);
2111
+ border: none;
2112
+ border-radius: var(--tcw-radius-sm);
2113
+ cursor: pointer;
2114
+ }
2115
+ .tcw-style-savebtn:hover { background: var(--tcw-accent-hover); }
2116
+
2117
+ .tcw-style-templates { display: flex; flex-direction: column; gap: 2px; max-height: 140px; overflow-y: auto; }
2118
+ .tcw-style-empty { font-size: 11px; color: var(--tcw-text-muted); padding: 4px 0; }
2119
+ .tcw-style-template { display: flex; align-items: center; gap: 4px; }
2120
+ .tcw-style-apply {
2121
+ flex: 1;
2122
+ min-width: 0;
2123
+ display: flex;
2124
+ align-items: center;
2125
+ gap: 7px;
2126
+ padding: 5px 7px;
2127
+ font-size: 12px;
2128
+ color: var(--tcw-text);
2129
+ background: transparent;
2130
+ border: none;
2131
+ border-radius: var(--tcw-radius-sm);
2132
+ cursor: pointer;
2133
+ text-align: left;
2134
+ }
2135
+ .tcw-style-apply:hover { background: var(--tcw-bg-surface); }
2136
+ .tcw-style-tdot { flex-shrink: 0; width: 9px; height: 9px; border-radius: 50%; }
2137
+ .tcw-style-tdel {
2138
+ display: inline-flex;
2139
+ align-items: center;
2140
+ justify-content: center;
2141
+ width: 26px;
2142
+ height: 26px;
2143
+ border: none;
2144
+ background: transparent;
2145
+ color: var(--tcw-text-muted);
2146
+ border-radius: var(--tcw-radius-sm);
2147
+ cursor: pointer;
2148
+ }
2149
+ .tcw-style-tdel:hover { background: var(--tcw-red-soft); color: var(--tcw-red); }
2150
+
2151
+ /* === Settings range slider === */
2152
+
2153
+ .tcw-settings-range {
2154
+ display: flex;
2155
+ align-items: center;
2156
+ gap: 8px;
2157
+ }
2158
+ .tcw-settings-range input[type='range'] {
2159
+ width: 110px;
2160
+ accent-color: var(--tcw-accent);
2161
+ cursor: pointer;
2162
+ }
2163
+ .tcw-settings-range-val {
2164
+ min-width: 38px;
2165
+ text-align: right;
2166
+ font-size: 12px;
2167
+ font-variant-numeric: tabular-nums;
2168
+ color: var(--tcw-text-dim);
2169
+ }
2170
+
2171
+ /* === Indicator settings dialog === */
2172
+
2173
+ .tcw-modal-narrow {
2174
+ max-width: 360px;
2175
+ }
2176
+ .tcw-indi-input {
2177
+ width: 110px;
2178
+ height: 30px;
2179
+ padding: 0 8px;
2180
+ font-size: 12px;
2181
+ color: var(--tcw-text);
2182
+ background: var(--tcw-bg-surface);
2183
+ border: 1px solid var(--tcw-border);
2184
+ border-radius: var(--tcw-radius-sm);
2185
+ outline: none;
2186
+ font-variant-numeric: tabular-nums;
2187
+ }
2188
+ .tcw-indi-input:focus {
2189
+ border-color: var(--tcw-accent);
2190
+ box-shadow: 0 0 0 2px var(--tcw-accent-soft);
2191
+ }
2192
+ .tcw-indi-color {
2193
+ width: 36px;
2194
+ height: 28px;
2195
+ padding: 2px;
2196
+ background: var(--tcw-bg-surface);
2197
+ border: 1px solid var(--tcw-border);
2198
+ border-radius: var(--tcw-radius-sm);
2199
+ cursor: pointer;
2200
+ }
2201
+
2202
+ /* === Object tree panel === */
2203
+
2204
+ .tcw-tree-panel {
2205
+ position: absolute;
2206
+ top: 50px;
2207
+ right: 12px;
2208
+ z-index: 39;
2209
+ width: 280px;
2210
+ max-width: calc(100vw - 24px);
2211
+ display: flex;
2212
+ flex-direction: column;
2213
+ background: var(--tcw-bg-elevated);
2214
+ border: 1px solid var(--tcw-border-strong);
2215
+ border-radius: var(--tcw-radius-lg);
2216
+ box-shadow: var(--tcw-shadow-lg);
2217
+ overflow: hidden;
2218
+ animation: tcw-alerts-in var(--tcw-dur, 160ms) var(--tcw-ease, ease) both;
2219
+ }
2220
+
2221
+ .tcw-tree-header {
2222
+ display: flex;
2223
+ align-items: center;
2224
+ justify-content: space-between;
2225
+ padding: 10px 12px;
2226
+ font-weight: 600;
2227
+ font-size: 13px;
2228
+ color: var(--tcw-text);
2229
+ border-bottom: 1px solid var(--tcw-border);
2230
+ }
2231
+ .tcw-tree-close {
2232
+ display: inline-flex;
2233
+ align-items: center;
2234
+ justify-content: center;
2235
+ width: 26px;
2236
+ height: 26px;
2237
+ border: none;
2238
+ background: transparent;
2239
+ color: var(--tcw-text-muted);
2240
+ border-radius: var(--tcw-radius-sm);
2241
+ cursor: pointer;
2242
+ }
2243
+ .tcw-tree-close:hover {
2244
+ background: var(--tcw-bg-surface);
2245
+ color: var(--tcw-text);
2246
+ }
2247
+
2248
+ .tcw-tree-section {
2249
+ padding: 6px;
2250
+ border-bottom: 1px solid var(--tcw-border);
2251
+ }
2252
+ .tcw-tree-section:last-child {
2253
+ border-bottom: none;
2254
+ }
2255
+ .tcw-tree-section-head {
2256
+ display: flex;
2257
+ align-items: center;
2258
+ justify-content: space-between;
2259
+ padding: 6px 8px 4px;
2260
+ font-size: 10px;
2261
+ font-weight: 700;
2262
+ text-transform: uppercase;
2263
+ letter-spacing: 0.05em;
2264
+ color: var(--tcw-text-muted);
2265
+ }
2266
+ .tcw-tree-add {
2267
+ display: inline-flex;
2268
+ align-items: center;
2269
+ justify-content: center;
2270
+ width: 22px;
2271
+ height: 22px;
2272
+ border: none;
2273
+ background: transparent;
2274
+ color: var(--tcw-text-muted);
2275
+ border-radius: var(--tcw-radius-sm);
2276
+ cursor: pointer;
2277
+ }
2278
+ .tcw-tree-add:hover {
2279
+ background: var(--tcw-accent-soft);
2280
+ color: var(--tcw-accent);
2281
+ }
2282
+ .tcw-tree-dot {
2283
+ flex-shrink: 0;
2284
+ width: 8px;
2285
+ height: 8px;
2286
+ border-radius: 50%;
2287
+ }
2288
+ .tcw-tree-list {
2289
+ max-height: 200px;
2290
+ overflow-y: auto;
2291
+ }
2292
+
2293
+ .tcw-tree-row {
2294
+ display: flex;
2295
+ align-items: center;
2296
+ justify-content: space-between;
2297
+ gap: 8px;
2298
+ padding: 6px 8px;
2299
+ border-radius: var(--tcw-radius-sm);
2300
+ }
2301
+ .tcw-tree-row:hover {
2302
+ background: var(--tcw-bg-surface);
2303
+ }
2304
+ .tcw-tree-hidden .tcw-tree-name {
2305
+ opacity: 0.5;
2306
+ }
2307
+ .tcw-tree-name {
2308
+ min-width: 0;
2309
+ font-size: 12px;
2310
+ color: var(--tcw-text);
2311
+ overflow: hidden;
2312
+ text-overflow: ellipsis;
2313
+ white-space: nowrap;
2314
+ }
2315
+ .tcw-tree-actions {
2316
+ display: flex;
2317
+ align-items: center;
2318
+ gap: 2px;
2319
+ flex-shrink: 0;
2320
+ }
2321
+ .tcw-tree-btn {
2322
+ display: inline-flex;
2323
+ align-items: center;
2324
+ justify-content: center;
2325
+ width: 26px;
2326
+ height: 26px;
2327
+ border: none;
2328
+ background: transparent;
2329
+ color: var(--tcw-text-muted);
2330
+ border-radius: var(--tcw-radius-sm);
2331
+ cursor: pointer;
2332
+ }
2333
+ .tcw-tree-btn:hover {
2334
+ background: var(--tcw-bg-elevated);
2335
+ color: var(--tcw-text);
2336
+ }
2337
+ .tcw-tree-btn.tcw-tree-on {
2338
+ color: var(--tcw-accent);
2339
+ }
2340
+ .tcw-tree-btn.tcw-tree-del:hover {
2341
+ background: var(--tcw-red-soft);
2342
+ color: var(--tcw-red);
2343
+ }
2344
+ .tcw-tree-empty {
2345
+ padding: 8px;
2346
+ font-size: 12px;
2347
+ color: var(--tcw-text-muted);
2348
+ }
2349
+
2350
+ @media (max-width: 640px) {
2351
+ .tcw-tree-panel {
2352
+ top: auto;
2353
+ bottom: 0;
2354
+ left: 0;
2355
+ right: 0;
2356
+ width: 100vw;
2357
+ max-width: 100vw;
2358
+ border-radius: var(--tcw-radius-xl) var(--tcw-radius-xl) 0 0;
2359
+ }
2360
+ .tcw-tree-list {
2361
+ max-height: 30vh;
2362
+ }
2363
+ .tcw-tree-section:last-child {
2364
+ padding-bottom: max(6px, env(safe-area-inset-bottom));
1433
2365
  }
1434
2366
  }
1435
2367
 
@@ -1444,13 +2376,13 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=requi
1444
2376
  transition-duration: 0.01ms !important;
1445
2377
  }
1446
2378
  }
1447
- `,u=0,d=`tcw-styles`;function f(){if(u++,u>1||document.getElementById(d))return;let e=document.createElement(`style`);e.id=d,e.textContent=l,document.head.appendChild(e)}function p(){if(u--,u>0)return;let e=document.getElementById(d);e&&e.remove()}var m={cursor:`<path d="M3 3l7.07 16.97 2.51-7.39 7.39-2.51L3 3z"/><path d="M13 13l6 6"/>`,trendingUp:`<polyline points="22 7 13.5 15.5 8.5 10.5 2 17"/><polyline points="16 7 22 7 22 13"/>`,minus:`<path d="M5 12h14"/>`,penLine:`<path d="M12 20h9"/><path d="M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z"/>`,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"/>`,square:`<rect width="18" height="18" x="3" y="3" rx="2"/>`,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"/>`,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"/>`,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"/>`,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"/>`,undo:`<path d="M3 7v6h6"/><path d="M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13"/>`,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"/>`,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"/>`,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"/>`,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"/>`,moon:`<path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"/>`,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"/>`,chevronDown:`<path d="m6 9 6 6 6-6"/>`,chevronUp:`<path d="m18 15-6-6-6 6"/>`,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"/>`,x:`<path d="M18 6 6 18"/><path d="m6 6 12 12"/>`,play:`<polygon points="6 3 20 12 6 21 6 3"/>`,pause:`<rect width="4" height="16" x="6" y="4"/><rect width="4" height="16" x="14" y="4"/>`,stop:`<rect width="14" height="14" x="5" y="5" rx="1"/>`,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"/>`};function h(e,t=14){let n=m[e];return n?`<svg xmlns="http://www.w3.org/2000/svg" width="${t}" height="${t}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${n}</svg>`:``}var g=class{trigger;panel;_isOpen=!1;onOutsideClick;onEscapeKey;onTriggerClick;constructor(e,t={}){this.trigger=e,this.panel=document.createElement(`div`),this.panel.className=`tcw-dropdown`,this.panel.style.width=t.width??`200px`,t.align===`right`?this.panel.style.right=`0`:this.panel.style.left=`0`,this.panel.style.display=`none`,e.style.position=`relative`,e.appendChild(this.panel),this.onTriggerClick=()=>{this._isOpen?this.close():this.open()},this.onOutsideClick=e=>{this.trigger.contains(e.target)||this.close()},this.onEscapeKey=e=>{e.key===`Escape`&&this.close()},e.addEventListener(`click`,this.onTriggerClick)}setContent(e){this.panel.innerHTML=e}open(){this._isOpen||(this._isOpen=!0,this.panel.style.display=``,document.addEventListener(`mousedown`,this.onOutsideClick),document.addEventListener(`keydown`,this.onEscapeKey))}close(){this._isOpen&&(this._isOpen=!1,this.panel.style.display=`none`,document.removeEventListener(`mousedown`,this.onOutsideClick),document.removeEventListener(`keydown`,this.onEscapeKey))}isOpen(){return this._isOpen}destroy(){this.trigger.removeEventListener(`click`,this.onTriggerClick),document.removeEventListener(`mousedown`,this.onOutsideClick),document.removeEventListener(`keydown`,this.onEscapeKey),this.panel.remove()}},_=class{config;callbacks;el;chartTypeDropdown=null;indicatorDropdown=null;tfButtons=[];chipsContainer=null;themeBtn=null;constructor(e,t,n){this.config=t,this.callbacks=n,this.el=document.createElement(`div`),this.el.className=`tcw-toolbar`,this.build(),e.appendChild(this.el)}build(){let{config:e,callbacks:t,el:n}=this,r=document.createElement(`button`);r.className=`tcw-toolbar-symbol`,r.dataset.role=`symbol`,r.addEventListener(`click`,t.onSymbolClick),n.appendChild(r),n.appendChild(this.sep());let i=document.createElement(`div`);i.className=`tcw-toolbar-group`;for(let n of e.timeframes){let e=document.createElement(`button`);e.className=`tcw-btn`,e.textContent=n.label,e.dataset.tf=n.value,e.addEventListener(`click`,()=>t.onTimeframe(n.value)),i.appendChild(e),this.tfButtons.push(e)}n.appendChild(i),n.appendChild(this.sep());let a=document.createElement(`div`);a.style.position=`relative`,a.style.display=`inline-flex`;let o=document.createElement(`button`);o.className=`tcw-dropdown-trigger`,o.dataset.role=`charttype`,a.appendChild(o),n.appendChild(a),this.chartTypeDropdown=new g(a,{width:`160px`}),this.buildChartTypeMenu(),n.appendChild(this.sep());let s=document.createElement(`div`);s.style.position=`relative`,s.style.display=`inline-flex`;let c=document.createElement(`button`);if(c.className=`tcw-dropdown-trigger`,c.dataset.role=`indicators`,s.appendChild(c),n.appendChild(s),this.indicatorDropdown=new g(s,{width:`280px`}),this.buildIndicatorMenu(),this.chipsContainer=document.createElement(`div`),this.chipsContainer.className=`tcw-indicator-chips`,n.appendChild(this.chipsContainer),n.appendChild(this.spacer()),t.onToggleReplay){let e=this.iconBtn(`play`,`Bar replay`,t.onToggleReplay);e.dataset.role=`replay`,n.appendChild(e)}let l=this.iconBtn(`camera`,`Screenshot`,t.onScreenshot);n.appendChild(l);let u=this.iconBtn(`settings`,`Chart Settings`,t.onSettings);n.appendChild(u),this.themeBtn=this.iconBtn(`moon`,`Toggle theme`,t.onToggleTheme),this.themeBtn.dataset.role=`theme`,n.appendChild(this.themeBtn)}buildChartTypeMenu(){if(!this.chartTypeDropdown)return;let e=this.config.chartTypes.map(e=>`<button class="tcw-dropdown-item" data-ct="${e.value}">${e.label}</button>`).join(``);this.chartTypeDropdown.setContent(e),this.chartTypeDropdown.panel.querySelectorAll(`.tcw-dropdown-item`).forEach(e=>{e.addEventListener(`click`,e=>{let t=e.currentTarget.dataset.ct;this.callbacks.onChartType(t),this.chartTypeDropdown?.close()})})}buildIndicatorMenu(){if(!this.indicatorDropdown)return;let{indicators:e,popularIndicatorIds:t}=this.config,n=e.filter(e=>t.includes(e.id)),r=e.filter(e=>!t.includes(e.id)),i=`<div class="tcw-dropdown-label">Popular</div>`;for(let e of n)i+=`<button class="tcw-dropdown-item" data-ind="${e.id}"><span>${e.name}</span><span class="tcw-tag">${e.type}</span></button>`;i+=`<div class="tcw-dropdown-divider"></div>`,i+=`<div class="tcw-dropdown-label">All</div>`;for(let e of r)i+=`<button class="tcw-dropdown-item" data-ind="${e.id}"><span>${e.name}</span><span class="tcw-tag">${e.type}</span></button>`;this.indicatorDropdown.setContent(i),this.indicatorDropdown.panel.querySelectorAll(`.tcw-dropdown-item[data-ind]`).forEach(e=>{e.addEventListener(`click`,e=>{let t=e.currentTarget.dataset.ind;this.callbacks.onAddIndicator(t)})})}update(e){let t=this.el.querySelector(`[data-role="symbol"]`);t&&(t.textContent=e.symbol);for(let t of this.tfButtons)t.classList.toggle(`tcw-active`,t.dataset.tf===e.timeframe);let n=this.el.querySelector(`[data-role="charttype"]`);if(n){let t=this.config.chartTypes.find(t=>t.value===e.chartType)?.label??`Candles`;n.innerHTML=`${h(`barChart`,14)} ${t} ${h(`chevronDown`,12)}`}let r=this.el.querySelector(`[data-role="indicators"]`);if(r){let t=e.activeIndicators.size,n=`${h(`trendingUp`,14)} Indicators`;t>0&&(n+=` <span class="tcw-badge-count">${t}</span>`),r.innerHTML=n}if(this.chipsContainer){let t=this.getActiveIndicatorList(e);this.chipsContainer.innerHTML=``;for(let e of t){let t=document.createElement(`div`);t.className=`tcw-indicator-chip`;let n=document.createElement(`span`);n.textContent=e.label,t.appendChild(n);let r=document.createElement(`button`);r.className=`tcw-chip-remove`,r.innerHTML=h(`x`,10),r.addEventListener(`click`,()=>this.callbacks.onRemoveIndicator(e.instanceId)),t.appendChild(r),this.chipsContainer.appendChild(t)}}this.themeBtn&&(this.themeBtn.innerHTML=e.isDark?h(`moon`,14):h(`sun`,14))}getActiveIndicatorList(e){let t=[];for(let[n,r]of e.activeIndicators.entries())t.push({instanceId:r,id:n,label:n.toUpperCase()});return t}sep(){let e=document.createElement(`span`);return e.className=`tcw-toolbar-sep`,e}spacer(){let e=document.createElement(`span`);return e.className=`tcw-toolbar-spacer`,e}iconBtn(e,t,n){let r=document.createElement(`button`);return r.className=`tcw-btn-icon`,r.title=t,r.innerHTML=h(e,14),r.addEventListener(`click`,n),r}destroy(){this.chartTypeDropdown?.destroy(),this.indicatorDropdown?.destroy(),this.el.remove()}},v=[`trendingUp`,`minus`,`penLine`,`hash`,`square`,`gitBranch`,`ruler`,`type`],y=class{config;callbacks;el;groupWraps=[];groupButtons=[];cursorBtn=null;magnetBtn=null;flyoutEl=null;constructor(e,t,n){this.config=t,this.callbacks=n,this.el=document.createElement(`div`),this.el.className=`tcw-sidebar`,this.build(),e.appendChild(this.el)}build(){let{config:e,callbacks:t,el:n}=this;this.cursorBtn=document.createElement(`button`),this.cursorBtn.className=`tcw-sidebar-btn`,this.cursorBtn.title=`Cursor`,this.cursorBtn.innerHTML=h(`cursor`,14),this.cursorBtn.addEventListener(`click`,t.onCancelDrawing),n.appendChild(this.cursorBtn),n.appendChild(this.divider()),e.drawingToolGroups.forEach((e,r)=>{let i=document.createElement(`div`);i.className=`tcw-tool-group-wrap`;let a=document.createElement(`button`);if(a.className=`tcw-sidebar-btn`,a.title=e.label,a.innerHTML=h(v[r]??`square`,14),e.tools.length>1){let e=document.createElement(`span`);e.className=`tcw-multi-dot`,a.appendChild(e)}a.addEventListener(`click`,()=>t.onDrawingTool(e.tools[0].value)),i.appendChild(a),i.addEventListener(`mouseenter`,()=>this.showFlyout(r)),i.addEventListener(`mouseleave`,()=>this.hideFlyout()),n.appendChild(i),this.groupWraps.push(i),this.groupButtons.push(a)});let r=document.createElement(`div`);r.className=`tcw-sidebar-spacer`,n.appendChild(r),n.appendChild(this.divider()),this.magnetBtn=document.createElement(`button`),this.magnetBtn.className=`tcw-sidebar-btn`,this.magnetBtn.title=`Magnet`,this.magnetBtn.innerHTML=h(`magnet`,14),this.magnetBtn.addEventListener(`click`,t.onToggleMagnet),n.appendChild(this.magnetBtn);let i=document.createElement(`button`);i.className=`tcw-sidebar-btn`,i.title=`Undo`,i.innerHTML=h(`undo`,14),i.addEventListener(`click`,t.onUndo),n.appendChild(i);let a=document.createElement(`button`);a.className=`tcw-sidebar-btn`,a.title=`Redo`,a.innerHTML=h(`redo`,14),a.addEventListener(`click`,t.onRedo),n.appendChild(a);let o=document.createElement(`button`);o.className=`tcw-sidebar-btn tcw-danger`,o.title=`Clear all`,o.innerHTML=h(`trash`,14),o.addEventListener(`click`,t.onClearDrawings),n.appendChild(o)}showFlyout(e){let t=this.config.drawingToolGroups[e];if(!t||t.tools.length<=1)return;this.hideFlyout();let n=document.createElement(`div`);n.className=`tcw-flyout`;let r=document.createElement(`div`);r.className=`tcw-flyout-header`,r.textContent=t.label,n.appendChild(r);for(let e of t.tools){let t=document.createElement(`button`);t.className=`tcw-flyout-item`,t.textContent=e.label,t.dataset.toolValue=e.value,t.addEventListener(`click`,()=>{this.callbacks.onDrawingTool(e.value),this.hideFlyout()}),n.appendChild(t)}this.flyoutEl=n,this.groupWraps[e].appendChild(n)}hideFlyout(){this.flyoutEl&&=(this.flyoutEl.remove(),null)}update(e){this.cursorBtn&&this.cursorBtn.classList.toggle(`tcw-active`,e.activeTool===null);let{drawingToolGroups:t}=this.config;for(let n=0;n<t.length;n++){let r=t[n].tools.some(t=>t.value===e.activeTool);this.groupButtons[n].classList.toggle(`tcw-active`,r)}this.flyoutEl&&this.flyoutEl.querySelectorAll(`.tcw-flyout-item`).forEach(t=>{let n=t;n.classList.toggle(`tcw-active`,n.dataset.toolValue===e.activeTool)}),this.magnetBtn&&(this.magnetBtn.classList.toggle(`tcw-active`,e.magnetEnabled),this.magnetBtn.title=e.magnetEnabled?`Magnet ON`:`Magnet OFF`)}divider(){let e=document.createElement(`div`);return e.className=`tcw-sidebar-divider`,e}destroy(){this.hideFlyout(),this.el.remove()}},b=[`style`,`display`,`scale`],x=class{callbacks;backdrop=null;modal=null;currentTab=`style`;currentSettings=null;bodyEl=null;tabButtons=[];constructor(e){this.callbacks=e}open(e){this.currentSettings={...e},this.currentTab=`style`,this.buildModal()}close(){this.backdrop?.remove(),this.modal?.remove(),this.backdrop=null,this.modal=null,this.bodyEl=null,this.tabButtons=[]}buildModal(){this.backdrop=document.createElement(`div`),this.backdrop.className=`tcw-modal-backdrop`,this.backdrop.addEventListener(`click`,()=>{this.callbacks.onClose(),this.close()}),document.body.appendChild(this.backdrop),this.modal=document.createElement(`div`),this.modal.className=`tcw-modal`;let e=document.createElement(`div`);e.className=`tcw-modal-header`;let t=document.createElement(`h3`);t.textContent=`Chart Settings`,e.appendChild(t);let n=document.createElement(`button`);n.className=`tcw-modal-close`,n.innerHTML=h(`x`,16),n.addEventListener(`click`,()=>{this.callbacks.onClose(),this.close()}),e.appendChild(n),this.modal.appendChild(e);let r=document.createElement(`div`);r.className=`tcw-modal-tabs`,this.tabButtons=[];for(let e of b){let t=document.createElement(`button`);t.className=`tcw-modal-tab`,t.textContent=e,t.dataset.tab=e,e===this.currentTab&&t.classList.add(`tcw-active`),t.addEventListener(`click`,()=>{this.currentTab=e,this.tabButtons.forEach(t=>t.classList.toggle(`tcw-active`,t.dataset.tab===e)),this.renderTabContent()}),r.appendChild(t),this.tabButtons.push(t)}this.modal.appendChild(r),this.bodyEl=document.createElement(`div`),this.bodyEl.className=`tcw-modal-body`,this.modal.appendChild(this.bodyEl),this.renderTabContent();let i=document.createElement(`div`);i.className=`tcw-modal-footer`;let a=document.createElement(`button`);a.className=`tcw-reset-link`,a.textContent=`Reset to defaults`,a.addEventListener(`click`,()=>this.callbacks.onReset()),i.appendChild(a);let o=document.createElement(`button`);o.className=`tcw-done-btn`,o.textContent=`Done`,o.addEventListener(`click`,()=>{this.callbacks.onClose(),this.close()}),i.appendChild(o),this.modal.appendChild(i),document.body.appendChild(this.modal);let s=e=>{e.key===`Escape`&&(document.removeEventListener(`keydown`,s),this.callbacks.onClose(),this.close())};document.addEventListener(`keydown`,s)}renderTabContent(){if(!(!this.bodyEl||!this.currentSettings))switch(this.bodyEl.innerHTML=``,this.currentTab){case`style`:this.renderStyleTab();break;case`display`:this.renderDisplayTab();break;case`scale`:this.renderScaleTab();break}}renderStyleTab(){if(!this.bodyEl||!this.currentSettings)return;let e=this.currentSettings,t=this.section(`Candle Colors`);t.appendChild(this.colorRow(`Up Body`,e.candleUpColor,e=>this.patch({candleUpColor:e}))),t.appendChild(this.colorRow(`Down Body`,e.candleDownColor,e=>this.patch({candleDownColor:e}))),t.appendChild(this.colorRow(`Up Wick`,e.candleUpWick,e=>this.patch({candleUpWick:e}))),t.appendChild(this.colorRow(`Down Wick`,e.candleDownWick,e=>this.patch({candleDownWick:e}))),this.bodyEl.appendChild(t);let n=this.section(`Background`);n.appendChild(this.colorRow(`Background`,e.backgroundColor,e=>this.patch({backgroundColor:e}))),n.appendChild(this.colorRow(`Grid`,e.gridColor,e=>this.patch({gridColor:e}))),this.bodyEl.appendChild(n)}renderDisplayTab(){if(!this.bodyEl||!this.currentSettings)return;let e=this.currentSettings,t=this.section();t.appendChild(this.toggleRow(`Grid Lines`,e.gridVisible,e=>this.patch({gridVisible:e}))),t.appendChild(this.toggleRow(`Volume`,e.volumeVisible,e=>this.patch({volumeVisible:e}))),t.appendChild(this.toggleRow(`Volume Profile`,e.volumeProfileVisible,e=>this.patch({volumeProfileVisible:e}))),t.appendChild(this.toggleRow(`OHLC Legend`,e.legendVisible,e=>this.patch({legendVisible:e}))),t.appendChild(this.toggleRow(`Bar Countdown`,e.barCountdown,e=>this.patch({barCountdown:e}))),t.appendChild(this.selectRow(`Crosshair Mode`,e.crosshairMode,[{label:`Magnet`,value:`magnet`},{label:`Normal`,value:`normal`},{label:`Hidden`,value:`hidden`}],e=>this.patch({crosshairMode:e}))),t.appendChild(this.selectRow(`Number Locale`,e.numberLocale,[{label:`en-US (65,234.00)`,value:`en-US`},{label:`de-DE (65.234,00)`,value:`de-DE`},{label:`fr-FR (65 234,00)`,value:`fr-FR`},{label:`vi-VN (65.234,00)`,value:`vi-VN`},{label:`en-IN (65,234.00)`,value:`en-IN`},{label:`ja-JP (65,234.00)`,value:`ja-JP`}],e=>this.patch({numberLocale:e}))),this.bodyEl.appendChild(t)}renderScaleTab(){if(!this.bodyEl||!this.currentSettings)return;let e=this.currentSettings,t=this.section();t.appendChild(this.toggleRow(`Auto Scale`,e.autoScale,e=>this.patch({autoScale:e}))),t.appendChild(this.toggleRow(`Log Scale`,e.logScale,e=>this.patch({logScale:e}))),this.bodyEl.appendChild(t)}patch(e){this.currentSettings&&Object.assign(this.currentSettings,e),this.callbacks.onChange(e)}section(e){let t=document.createElement(`div`);if(t.className=`tcw-settings-section`,e){let n=document.createElement(`div`);n.className=`tcw-settings-section-title`,n.textContent=e,t.appendChild(n)}return t}colorRow(e,t,n){let r=document.createElement(`div`);r.className=`tcw-settings-row`;let i=document.createElement(`span`);i.className=`tcw-settings-label`,i.textContent=e,r.appendChild(i);let a=document.createElement(`div`);a.className=`tcw-color-picker-wrap`;let o=document.createElement(`input`);o.type=`color`,o.value=t;let s=document.createElement(`span`);return s.className=`tcw-color-hex`,s.textContent=t,o.addEventListener(`input`,()=>{s.textContent=o.value,n(o.value)}),a.appendChild(o),a.appendChild(s),r.appendChild(a),r}toggleRow(e,t,n){let r=document.createElement(`div`);r.className=`tcw-settings-row`;let i=document.createElement(`span`);i.className=`tcw-settings-label`,i.textContent=e,r.appendChild(i);let a=document.createElement(`button`);return a.className=`tcw-toggle${t?` tcw-on`:``}`,a.addEventListener(`click`,()=>{let e=!a.classList.contains(`tcw-on`);a.classList.toggle(`tcw-on`,e),n(e)}),r.appendChild(a),r}selectRow(e,t,n,r){let i=document.createElement(`div`);i.className=`tcw-settings-row`;let a=document.createElement(`span`);a.className=`tcw-settings-label`,a.textContent=e,i.appendChild(a);let o=document.createElement(`select`);o.className=`tcw-settings-select`;for(let e of n){let n=document.createElement(`option`);n.value=e.value,n.textContent=e.label,e.value===t&&(n.selected=!0),o.appendChild(n)}return o.addEventListener(`change`,()=>r(o.value)),i.appendChild(o),i}destroy(){this.close()}},S=class{el;dotEl;messageEl;infoEl;constructor(e){this.el=document.createElement(`div`),this.el.className=`tcw-statusbar`;let t=document.createElement(`div`);t.className=`tcw-status-indicator`,this.dotEl=document.createElement(`span`),this.dotEl.className=`tcw-status-dot`,t.appendChild(this.dotEl),this.messageEl=document.createElement(`span`),t.appendChild(this.messageEl),this.el.appendChild(t),this.infoEl=document.createElement(`span`),this.el.appendChild(this.infoEl),e.appendChild(this.el)}update(e){this.dotEl.className=`tcw-status-dot`,e.connectionState===`connected`?this.dotEl.classList.add(`tcw-connected`):e.connectionState===`error`&&this.dotEl.classList.add(`tcw-error`),this.messageEl.textContent=e.message,this.infoEl.textContent=`${e.symbol} ${e.timeframe}`}destroy(){this.el.remove()}},C=class{backdrop=null;modal=null;input=null;list=null;items=[];filtered=[];selectedIndex=0;callbacks;boundKeydown;constructor(e){this.callbacks=e,this.boundKeydown=this.handleKeydown.bind(this)}open(e){if(this.backdrop)return;this.items=e,this.filtered=e,this.selectedIndex=0,this.backdrop=document.createElement(`div`),this.backdrop.className=`tcw-modal-backdrop`,this.backdrop.addEventListener(`click`,()=>this.close()),this.modal=document.createElement(`div`),this.modal.className=`tcw-cmd-palette`;let t=document.createElement(`div`);t.className=`tcw-cmd-header`;let n=document.createElement(`span`);n.className=`tcw-cmd-icon`,n.textContent=`⌕`,t.appendChild(n),this.input=document.createElement(`input`),this.input.className=`tcw-cmd-input`,this.input.type=`text`,this.input.placeholder=`Search indicators, chart types, tools...`,this.input.addEventListener(`input`,()=>this.filter()),t.appendChild(this.input);let r=document.createElement(`span`);r.className=`tcw-cmd-hint`,r.textContent=`ESC`,t.appendChild(r),this.modal.appendChild(t),this.list=document.createElement(`div`),this.list.className=`tcw-cmd-list`,this.modal.appendChild(this.list);let i=document.createElement(`div`);i.className=`tcw-cmd-footer`,i.innerHTML=`<span>↑↓ Navigate</span><span>⏎ Select</span><span>Esc Close</span>`,this.modal.appendChild(i),document.body.appendChild(this.backdrop),document.body.appendChild(this.modal),this.renderList(),this.input.focus(),document.addEventListener(`keydown`,this.boundKeydown)}close(){document.removeEventListener(`keydown`,this.boundKeydown),this.backdrop?.remove(),this.modal?.remove(),this.backdrop=null,this.modal=null,this.input=null,this.list=null,this.callbacks.onClose()}isOpen(){return this.backdrop!==null}filter(){let e=this.input?.value.toLowerCase().trim()??``;e?this.filtered=this.items.filter(t=>t.label.toLowerCase().includes(e)||t.category.toLowerCase().includes(e)||t.id.toLowerCase().includes(e)):this.filtered=this.items,this.selectedIndex=0,this.renderList()}renderList(){if(!this.list)return;if(this.list.innerHTML=``,this.filtered.length===0){let e=document.createElement(`div`);e.className=`tcw-cmd-empty`,e.textContent=`No results found`,this.list.appendChild(e);return}let e=``;for(let t=0;t<this.filtered.length;t++){let n=this.filtered[t];if(n.category!==e){e=n.category;let t=document.createElement(`div`);t.className=`tcw-cmd-category`,t.textContent=this.categoryLabel(e),this.list.appendChild(t)}let r=document.createElement(`button`);r.className=`tcw-cmd-item`,t===this.selectedIndex&&r.classList.add(`tcw-selected`),n.active&&r.classList.add(`tcw-active`),r.dataset.index=String(t);let i=document.createElement(`span`);if(i.className=`tcw-cmd-item-label`,i.textContent=n.label,r.appendChild(i),n.active){let e=document.createElement(`span`);e.className=`tcw-cmd-check`,e.textContent=`✓`,r.appendChild(e)}if(n.shortcut){let e=document.createElement(`kbd`);e.className=`tcw-cmd-kbd`,e.textContent=n.shortcut,r.appendChild(e)}r.addEventListener(`click`,()=>this.select(t)),r.addEventListener(`mouseenter`,()=>{this.selectedIndex=t,this.updateSelection()}),this.list.appendChild(r)}}updateSelection(){if(!this.list)return;let e=this.list.querySelectorAll(`.tcw-cmd-item`);e.forEach((e,t)=>{e.classList.toggle(`tcw-selected`,t===this.selectedIndex)}),e[this.selectedIndex]?.scrollIntoView({block:`nearest`})}select(e){let t=this.filtered[e];if(t){switch(t.category){case`indicator`:this.callbacks.onIndicator(t.id);break;case`chartType`:this.callbacks.onChartType(t.id);break;case`drawing`:this.callbacks.onDrawingTool(t.id);break;case`timeframe`:this.callbacks.onTimeframe(t.id);break;case`action`:this.callbacks.onAction(t.id);break}this.close()}}handleKeydown(e){switch(e.key){case`Escape`:e.preventDefault(),this.close();break;case`ArrowDown`:e.preventDefault(),this.filtered.length>0&&(this.selectedIndex=(this.selectedIndex+1)%this.filtered.length,this.updateSelection());break;case`ArrowUp`:e.preventDefault(),this.filtered.length>0&&(this.selectedIndex=(this.selectedIndex-1+this.filtered.length)%this.filtered.length,this.updateSelection());break;case`Enter`:e.preventDefault(),this.select(this.selectedIndex);break}}categoryLabel(e){switch(e){case`indicator`:return`Indicators`;case`chartType`:return`Chart Types`;case`drawing`:return`Drawing Tools`;case`timeframe`:return`Timeframes`;case`action`:return`Actions`;default:return e}}destroy(){this.close()}},w=class{backdrop=null;modal=null;input=null;list=null;symbols=[];current=``;filtered=[];selectedIndex=0;callbacks;boundKeydown;constructor(e){this.callbacks=e,this.boundKeydown=this.handleKeydown.bind(this)}open(e,t){if(this.backdrop)return;this.symbols=e,this.current=t,this.filtered=e.map(e=>({symbol:e,score:0})),this.selectedIndex=Math.max(0,e.indexOf(t)),this.backdrop=document.createElement(`div`),this.backdrop.className=`tcw-modal-backdrop`,this.backdrop.addEventListener(`click`,()=>this.close()),this.modal=document.createElement(`div`),this.modal.className=`tcw-cmd-palette`;let n=document.createElement(`div`);n.className=`tcw-cmd-header`;let r=document.createElement(`span`);r.className=`tcw-cmd-icon`,r.innerHTML=O(),n.appendChild(r),this.input=document.createElement(`input`),this.input.className=`tcw-cmd-input`,this.input.type=`text`,this.input.placeholder=`Search symbol… (e.g. BTC, ETH, AAPL)`,this.input.autocomplete=`off`,this.input.spellcheck=!1,this.input.addEventListener(`input`,()=>this.filter()),n.appendChild(this.input);let i=document.createElement(`span`);i.className=`tcw-cmd-hint`,i.textContent=`ESC`,n.appendChild(i),this.modal.appendChild(n),this.list=document.createElement(`div`),this.list.className=`tcw-cmd-list`,this.modal.appendChild(this.list);let a=document.createElement(`div`);a.className=`tcw-cmd-footer`,a.innerHTML=`<span>↑↓ Navigate</span><span>⏎ Open</span><span>Esc Close</span>`,this.modal.appendChild(a),document.body.appendChild(this.backdrop),document.body.appendChild(this.modal),this.renderList(),this.input.focus(),document.addEventListener(`keydown`,this.boundKeydown)}close(){document.removeEventListener(`keydown`,this.boundKeydown),this.backdrop?.remove(),this.modal?.remove(),this.backdrop=null,this.modal=null,this.input=null,this.list=null,this.callbacks.onClose()}isOpen(){return this.backdrop!==null}destroy(){this.close()}filter(){let e=(this.input?.value??``).toUpperCase().trim();e?this.filtered=this.symbols.map(t=>({symbol:t,score:T(t.toUpperCase(),e)})).filter(e=>e.score>0).sort((e,t)=>t.score-e.score):this.filtered=this.symbols.map(e=>({symbol:e,score:0})),this.selectedIndex=0,this.renderList()}renderList(){if(!this.list)return;if(this.list.innerHTML=``,this.filtered.length===0){let e=document.createElement(`div`);e.className=`tcw-cmd-empty`,e.textContent=`No symbols match`,this.list.appendChild(e);return}let e=(this.input?.value??``).toUpperCase().trim();for(let t=0;t<this.filtered.length;t++){let{symbol:n}=this.filtered[t],r=document.createElement(`button`);r.className=`tcw-cmd-item`,t===this.selectedIndex&&r.classList.add(`tcw-selected`),n===this.current&&r.classList.add(`tcw-active`);let i=document.createElement(`span`);if(i.className=`tcw-cmd-item-label`,i.innerHTML=E(n,e),r.appendChild(i),n===this.current){let e=document.createElement(`span`);e.className=`tcw-cmd-check`,e.textContent=`✓`,r.appendChild(e)}r.addEventListener(`click`,()=>this.pick(t)),r.addEventListener(`mouseenter`,()=>{this.selectedIndex=t,this.updateSelection()}),this.list.appendChild(r)}}updateSelection(){if(!this.list)return;let e=this.list.querySelectorAll(`.tcw-cmd-item`);e.forEach((e,t)=>e.classList.toggle(`tcw-selected`,t===this.selectedIndex)),e[this.selectedIndex]?.scrollIntoView({block:`nearest`})}pick(e){let t=this.filtered[e];t&&(this.callbacks.onPick(t.symbol),this.close())}handleKeydown(e){switch(e.key){case`Escape`:e.preventDefault(),this.close();break;case`ArrowDown`:e.preventDefault(),this.filtered.length>0&&(this.selectedIndex=(this.selectedIndex+1)%this.filtered.length,this.updateSelection());break;case`ArrowUp`:e.preventDefault(),this.filtered.length>0&&(this.selectedIndex=(this.selectedIndex-1+this.filtered.length)%this.filtered.length,this.updateSelection());break;case`Enter`:e.preventDefault(),this.pick(this.selectedIndex);break}}};function T(e,t){if(e===t)return 1e3;if(e.startsWith(t))return 500+(50-Math.min(50,e.length-t.length));if(e.includes(t))return 200+(50-Math.min(50,e.length-t.length));let n=0,r=-1,i=0;for(let a=0;a<e.length&&n<t.length;a++)e[a]===t[n]&&(r>=0&&(i+=a-r-1),r=a,n++);return n<t.length?0:100-Math.min(99,i)}function E(e,t){if(!t)return D(e);let n=e.toUpperCase(),r=``,i=0;for(let a=0;a<e.length;a++)i<t.length&&n[a]===t[i]?(r+=`<mark style="background:transparent;color:var(--tcw-accent);font-weight:700">${D(e[a])}</mark>`,i++):r+=D(e[a]);return r}function D(e){return e.replace(/[&<>"']/g,e=>({"&":`&amp;`,"<":`&lt;`,">":`&gt;`,'"':`&quot;`,"'":`&#39;`})[e])}function O(){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>`}var k=typeof navigator<`u`&&/mac|iphone|ipad|ipod/i.test(navigator.platform||navigator.userAgent)?`⌘`:`Ctrl`,A=[{title:`Search & navigation`,entries:[{keys:[k,`K`],label:`Command palette`},{keys:[k,`P`],label:`Symbol search`},{keys:[`?`],label:`Show this sheet`}]},{title:`Chart manipulation`,entries:[{keys:[`Shift`,`Drag`],label:`Measure tool (bars × price Δ)`},{keys:[`Drag`,`Price axis`],label:`Compress / expand vertical scale`},{keys:[`Drag`,`Time axis`],label:`Zoom time axis`},{keys:[`Double-click`,`Price axis`],label:`Re-enable auto-scale`},{keys:[`Double-click`,`Time axis`],label:`Fit content`},{keys:[`Scroll`],label:`Zoom around cursor`}]},{title:`Keyboard`,entries:[{keys:[`←`,`→`],label:`Pan one bar`},{keys:[`+`,`−`],label:`Zoom in / out`},{keys:[`Home`],label:`Scroll to start`},{keys:[`End`],label:`Scroll to end (live edge)`},{keys:[`F`],label:`Fit content`}]},{title:`Drawing`,entries:[{keys:[k,`Z`],label:`Undo`},{keys:[k,`Shift`,`Z`],label:`Redo`},{keys:[`Esc`],label:`Cancel active drawing`}]}],j=class{backdrop=null;modal=null;callbacks;boundKeydown;constructor(e){this.callbacks=e,this.boundKeydown=e=>{e.key===`Escape`&&(e.preventDefault(),this.close())}}open(){if(this.backdrop)return;this.backdrop=document.createElement(`div`),this.backdrop.className=`tcw-modal-backdrop`,this.backdrop.addEventListener(`click`,()=>this.close()),this.modal=document.createElement(`div`),this.modal.className=`tcw-modal tcw-hotkey-sheet`,this.modal.style.width=`640px`;let e=document.createElement(`div`);e.className=`tcw-modal-header`,e.innerHTML=`<h3>Keyboard shortcuts</h3>`;let t=document.createElement(`button`);t.className=`tcw-modal-close`,t.setAttribute(`aria-label`,`Close`),t.innerHTML=`×`,t.addEventListener(`click`,()=>this.close()),e.appendChild(t),this.modal.appendChild(e);let n=document.createElement(`div`);n.className=`tcw-modal-body`;let r=document.createElement(`div`);r.className=`tcw-hotkey-grid`;for(let e of A){let t=document.createElement(`section`);t.className=`tcw-hotkey-section`;let n=document.createElement(`div`);n.className=`tcw-settings-section-title`,n.textContent=e.title,t.appendChild(n);for(let n of e.entries){let e=document.createElement(`div`);e.className=`tcw-hotkey-row`;let r=document.createElement(`div`);r.className=`tcw-hotkey-keys`;for(let e=0;e<n.keys.length;e++){if(e>0){let e=document.createElement(`span`);e.className=`tcw-hotkey-sep`,e.textContent=`+`,r.appendChild(e)}let t=document.createElement(`kbd`);t.className=`tcw-cmd-kbd`,t.textContent=n.keys[e],r.appendChild(t)}e.appendChild(r);let i=document.createElement(`span`);i.className=`tcw-hotkey-label`,i.textContent=n.label,e.appendChild(i),t.appendChild(e)}r.appendChild(t)}n.appendChild(r),this.modal.appendChild(n);let i=document.createElement(`div`);i.className=`tcw-modal-footer`,i.innerHTML=`<span style="font-size:11px;color:var(--tcw-text-muted)">Press ? anytime to show this sheet</span>`;let a=document.createElement(`button`);a.className=`tcw-done-btn`,a.textContent=`Got it`,a.addEventListener(`click`,()=>this.close()),i.appendChild(a),this.modal.appendChild(i),document.body.appendChild(this.backdrop),document.body.appendChild(this.modal),document.addEventListener(`keydown`,this.boundKeydown)}close(){document.removeEventListener(`keydown`,this.boundKeydown),this.backdrop?.remove(),this.modal?.remove(),this.backdrop=null,this.modal=null,this.callbacks.onClose()}isOpen(){return this.backdrop!==null}destroy(){this.close()}},M=[.5,1,2,5,10,20,50,100],N=class{root=null;scrubber=null;progressLabel=null;playBtn=null;state=`stopped`;total=0;speed=5;callbacks;constructor(e){this.callbacks=e}mount(e,t){this.root||(this.total=Math.max(0,t.total),this.speed=t.speed??5,this.state=`paused`,this.root=document.createElement(`div`),this.root.className=`tcw-replay-bar`,this.root.innerHTML=this.markup(),e.appendChild(this.root),this.wireEvents(),this.syncUi())}unmount(){this.root?.remove(),this.root=null,this.scrubber=null,this.progressLabel=null,this.playBtn=null,this.state=`stopped`}isMounted(){return this.root!==null}setState(e){this.state=e,this.syncUi()}setProgress(e,t){this.total=t,this.scrubber&&(this.scrubber.max=String(Math.max(0,t-1)),this.scrubber.value=String(e)),this.progressLabel&&(this.progressLabel.textContent=`${e+1} / ${t}`)}destroy(){this.unmount()}markup(){let e=M.map(e=>`<option value="${e}"${e===this.speed?` selected`:``}>${e}× bars/s</option>`).join(``);return`
1448
- <button class="tcw-replay-btn" data-act="close" title="Exit replay" aria-label="Exit replay">${R()}</button>
1449
- <button class="tcw-replay-btn" data-act="stepBack" title="Step back" aria-label="Step back">${I()}</button>
1450
- <button class="tcw-replay-btn tcw-replay-play" data-act="play" title="Play / pause" aria-label="Play / pause">${P()}</button>
1451
- <button class="tcw-replay-btn" data-act="stepForward" title="Step forward" aria-label="Step forward">${L()}</button>
2379
+ `,f=0,p=`tcw-styles`;function m(){if(f++,f>1||document.getElementById(p))return;let e=document.createElement(`style`);e.id=p,e.textContent=d,document.head.appendChild(e)}function h(){if(f--,f>0)return;let e=document.getElementById(p);e&&e.remove()}var g={cursor:`<path d="M3 3l7.07 16.97 2.51-7.39 7.39-2.51L3 3z"/><path d="M13 13l6 6"/>`,trendingUp:`<polyline points="22 7 13.5 15.5 8.5 10.5 2 17"/><polyline points="16 7 22 7 22 13"/>`,minus:`<path d="M5 12h14"/>`,penLine:`<path d="M12 20h9"/><path d="M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4Z"/>`,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"/>`,square:`<rect width="18" height="18" x="3" y="3" rx="2"/>`,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"/>`,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"/>`,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"/>`,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"/>`,undo:`<path d="M3 7v6h6"/><path d="M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13"/>`,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"/>`,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"/>`,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"/>`,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"/>`,moon:`<path d="M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z"/>`,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"/>`,chevronDown:`<path d="m6 9 6 6 6-6"/>`,chevronUp:`<path d="m18 15-6-6-6 6"/>`,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"/>`,x:`<path d="M18 6 6 18"/><path d="m6 6 12 12"/>`,play:`<polygon points="6 3 20 12 6 21 6 3"/>`,pause:`<rect width="4" height="16" x="6" y="4"/><rect width="4" height="16" x="14" y="4"/>`,stop:`<rect width="14" height="14" x="5" y="5" rx="1"/>`,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"/>`,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"/>`,plus:`<path d="M5 12h14"/><path d="M12 5v14"/>`,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"/>`,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"/>`,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"/>`,lock:`<rect width="18" height="11" x="3" y="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/>`,unlock:`<rect width="18" height="11" x="3" y="11" rx="2"/><path d="M7 11V7a5 5 0 0 1 9.9-1"/>`,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"/>`,trendingDown:`<polyline points="22 17 13.5 8.5 8.5 13.5 2 7"/><polyline points="16 17 22 17 22 11"/>`,check:`<polyline points="20 6 9 17 4 12"/>`,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"/>`};function _(e,t=14){let n=g[e];return n?`<svg xmlns="http://www.w3.org/2000/svg" width="${t}" height="${t}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">${n}</svg>`:``}var v=class{trigger;panel;_isOpen=!1;onOutsideClick;onEscapeKey;onTriggerClick;constructor(e,t={}){this.trigger=e,this.panel=document.createElement(`div`),this.panel.className=`tcw-dropdown`,this.panel.style.width=t.width??`200px`,t.align===`right`?this.panel.style.right=`0`:this.panel.style.left=`0`,this.panel.style.display=`none`,e.style.position=`relative`,e.appendChild(this.panel),this.onTriggerClick=()=>{this._isOpen?this.close():this.open()},this.onOutsideClick=e=>{this.trigger.contains(e.target)||this.close()},this.onEscapeKey=e=>{e.key===`Escape`&&this.close()},e.addEventListener(`click`,this.onTriggerClick)}setContent(e){this.panel.innerHTML=e}open(){this._isOpen||(this._isOpen=!0,this.panel.style.display=``,document.addEventListener(`mousedown`,this.onOutsideClick),document.addEventListener(`keydown`,this.onEscapeKey))}close(){this._isOpen&&(this._isOpen=!1,this.panel.style.display=`none`,document.removeEventListener(`mousedown`,this.onOutsideClick),document.removeEventListener(`keydown`,this.onEscapeKey))}isOpen(){return this._isOpen}destroy(){this.trigger.removeEventListener(`click`,this.onTriggerClick),document.removeEventListener(`mousedown`,this.onOutsideClick),document.removeEventListener(`keydown`,this.onEscapeKey),this.panel.remove()}},y=class{config;callbacks;el;chartTypeDropdown=null;indicatorDropdown=null;tfButtons=[];chipsContainer=null;themeBtn=null;constructor(e,t,n){this.config=t,this.callbacks=n,this.el=document.createElement(`div`),this.el.className=`tcw-toolbar`,this.build(),e.appendChild(this.el)}build(){let{config:e,callbacks:t,el:n}=this,r=document.createElement(`button`);r.className=`tcw-toolbar-symbol`,r.dataset.role=`symbol`,r.addEventListener(`click`,t.onSymbolClick),n.appendChild(r),n.appendChild(this.sep());let i=document.createElement(`div`);i.className=`tcw-toolbar-group`;for(let n of e.timeframes){let e=document.createElement(`button`);e.className=`tcw-btn`,e.textContent=n.label,e.dataset.tf=n.value,e.addEventListener(`click`,()=>t.onTimeframe(n.value)),i.appendChild(e),this.tfButtons.push(e)}n.appendChild(i),n.appendChild(this.sep());let a=document.createElement(`div`);a.style.position=`relative`,a.style.display=`inline-flex`;let o=document.createElement(`button`);o.className=`tcw-dropdown-trigger`,o.dataset.role=`charttype`,a.appendChild(o),n.appendChild(a),this.chartTypeDropdown=new v(a,{width:`160px`}),this.buildChartTypeMenu(),n.appendChild(this.sep());let s=document.createElement(`div`);s.style.position=`relative`,s.style.display=`inline-flex`;let c=document.createElement(`button`);if(c.className=`tcw-dropdown-trigger`,c.dataset.role=`indicators`,s.appendChild(c),n.appendChild(s),this.indicatorDropdown=new v(s,{width:`280px`}),this.buildIndicatorMenu(),this.chipsContainer=document.createElement(`div`),this.chipsContainer.className=`tcw-indicator-chips`,n.appendChild(this.chipsContainer),n.appendChild(this.spacer()),t.onToggleReplay){let e=this.iconBtn(`play`,`Bar replay`,t.onToggleReplay);e.dataset.role=`replay`,n.appendChild(e)}if(t.onBracket){let e=t.onBracket,r=this.iconBtn(`trendingUp`,`Long bracket`,()=>e(`buy`));r.dataset.role=`long`,r.classList.add(`tcw-btn-long`),n.appendChild(r);let i=this.iconBtn(`trendingDown`,`Short bracket`,()=>e(`sell`));i.dataset.role=`short`,i.classList.add(`tcw-btn-short`),n.appendChild(i)}if(t.onToggleLadder){let e=this.iconBtn(`ladder`,`Depth ladder`,t.onToggleLadder);e.dataset.role=`ladder`,n.appendChild(e)}if(t.onToggleObjects){let e=this.iconBtn(`layers`,`Objects`,t.onToggleObjects);e.dataset.role=`objects`,n.appendChild(e)}if(t.onToggleAlerts){let e=this.iconBtn(`bell`,`Price alerts`,t.onToggleAlerts);e.dataset.role=`alerts`,n.appendChild(e)}let l=this.iconBtn(`camera`,`Screenshot`,t.onScreenshot);n.appendChild(l);let u=this.iconBtn(`settings`,`Chart Settings`,t.onSettings);n.appendChild(u),this.themeBtn=this.iconBtn(`moon`,`Toggle theme`,t.onToggleTheme),this.themeBtn.dataset.role=`theme`,n.appendChild(this.themeBtn)}buildChartTypeMenu(){if(!this.chartTypeDropdown)return;let e=this.config.chartTypes.map(e=>`<button class="tcw-dropdown-item" data-ct="${e.value}">${e.label}</button>`).join(``);this.chartTypeDropdown.setContent(e),this.chartTypeDropdown.panel.querySelectorAll(`.tcw-dropdown-item`).forEach(e=>{e.addEventListener(`click`,e=>{let t=e.currentTarget.dataset.ct;this.callbacks.onChartType(t),this.chartTypeDropdown?.close()})})}buildIndicatorMenu(){if(!this.indicatorDropdown)return;let{indicators:e,popularIndicatorIds:t}=this.config,n=e.filter(e=>t.includes(e.id)),r=e.filter(e=>!t.includes(e.id)),i=`<div class="tcw-dropdown-label">Popular</div>`;for(let e of n)i+=`<button class="tcw-dropdown-item" data-ind="${e.id}"><span>${e.name}</span><span class="tcw-tag">${e.type}</span></button>`;i+=`<div class="tcw-dropdown-divider"></div>`,i+=`<div class="tcw-dropdown-label">All</div>`;for(let e of r)i+=`<button class="tcw-dropdown-item" data-ind="${e.id}"><span>${e.name}</span><span class="tcw-tag">${e.type}</span></button>`;this.indicatorDropdown.setContent(i),this.indicatorDropdown.panel.querySelectorAll(`.tcw-dropdown-item[data-ind]`).forEach(e=>{e.addEventListener(`click`,e=>{let t=e.currentTarget.dataset.ind;this.callbacks.onAddIndicator(t)})})}update(e){let t=this.el.querySelector(`[data-role="symbol"]`);t&&(t.textContent=e.symbol);for(let t of this.tfButtons)t.classList.toggle(`tcw-active`,t.dataset.tf===e.timeframe);let n=this.el.querySelector(`[data-role="charttype"]`);if(n){let t=this.config.chartTypes.find(t=>t.value===e.chartType)?.label??`Candles`;n.innerHTML=`${_(`barChart`,14)} ${t} ${_(`chevronDown`,12)}`}let r=this.el.querySelector(`[data-role="indicators"]`);if(r){let t=e.activeIndicators.size,n=`${_(`trendingUp`,14)} Indicators`;t>0&&(n+=` <span class="tcw-badge-count">${t}</span>`),r.innerHTML=n}if(this.chipsContainer){let t=this.getActiveIndicatorList(e);this.chipsContainer.innerHTML=``;for(let e of t){let t=document.createElement(`div`);t.className=`tcw-indicator-chip`;let n=document.createElement(`span`);n.textContent=e.label,t.appendChild(n);let r=document.createElement(`button`);r.className=`tcw-chip-remove`,r.innerHTML=_(`x`,10),r.addEventListener(`click`,()=>this.callbacks.onRemoveIndicator(e.instanceId)),t.appendChild(r),this.chipsContainer.appendChild(t)}}this.themeBtn&&(this.themeBtn.innerHTML=e.isDark?_(`moon`,14):_(`sun`,14))}getActiveIndicatorList(e){let t=[];for(let[n,r]of e.activeIndicators.entries())t.push({instanceId:r,id:n,label:n.toUpperCase()});return t}sep(){let e=document.createElement(`span`);return e.className=`tcw-toolbar-sep`,e}spacer(){let e=document.createElement(`span`);return e.className=`tcw-toolbar-spacer`,e}iconBtn(e,t,n){let r=document.createElement(`button`);return r.className=`tcw-btn-icon`,r.title=t,r.innerHTML=_(e,14),r.addEventListener(`click`,n),r}destroy(){this.chartTypeDropdown?.destroy(),this.indicatorDropdown?.destroy(),this.el.remove()}},ee=[`trendingUp`,`minus`,`penLine`,`hash`,`square`,`gitBranch`,`ruler`,`type`],te={trendLine:`trendingUp`,ray:`trendingUp`,extendedLine:`trendingUp`,horizontalLine:`minus`,verticalLine:`penLine`,rectangle:`square`,ellipse:`square`,triangle:`square`,arrow:`trendingUp`,parallelChannel:`gitBranch`,regressionChannel:`gitBranch`,pitchfork:`gitBranch`,fibRetracement:`hash`,fibExtension:`hash`,fibTimeZones:`hash`,gannBox:`hash`,gannFan:`gitBranch`,elliottWave:`trendingUp`,priceRange:`ruler`,dateRange:`ruler`,measure:`ruler`,textAnnotation:`type`,anchoredVWAP:`trendingUp`,volumeProfileRange:`barChart`};function ne(e){return te[e]??`penLine`}function re(e,t){for(let n of e){let e=n.tools.find(e=>e.value===t);if(e)return e.label}return t}var ie=class{config;callbacks;el;groupWraps=[];groupButtons=[];cursorBtn=null;magnetBtn=null;flyoutEl=null;favoritesEl=null;favoritesDivider=null;favorites=[];constructor(e,t,n){this.config=t,this.callbacks=n,this.el=document.createElement(`div`),this.el.className=`tcw-sidebar`,this.build(),e.appendChild(this.el)}build(){let{config:e,callbacks:t,el:n}=this;this.cursorBtn=document.createElement(`button`),this.cursorBtn.className=`tcw-sidebar-btn`,this.cursorBtn.title=`Cursor`,this.cursorBtn.innerHTML=_(`cursor`,14),this.cursorBtn.addEventListener(`click`,t.onCancelDrawing),n.appendChild(this.cursorBtn),n.appendChild(this.divider()),t.onToggleFavorite&&(this.favorites=[...e.favorites??[]],this.favoritesEl=document.createElement(`div`),this.favoritesEl.className=`tcw-sidebar-favorites`,n.appendChild(this.favoritesEl),this.favoritesDivider=this.divider(),n.appendChild(this.favoritesDivider),this.renderFavorites()),e.drawingToolGroups.forEach((e,r)=>{let i=document.createElement(`div`);i.className=`tcw-tool-group-wrap`;let a=document.createElement(`button`);if(a.className=`tcw-sidebar-btn`,a.title=e.label,a.innerHTML=_(ee[r]??`square`,14),e.tools.length>1){let e=document.createElement(`span`);e.className=`tcw-multi-dot`,a.appendChild(e)}a.addEventListener(`click`,()=>t.onDrawingTool(e.tools[0].value)),i.appendChild(a),i.addEventListener(`mouseenter`,()=>this.showFlyout(r)),i.addEventListener(`mouseleave`,()=>this.hideFlyout()),n.appendChild(i),this.groupWraps.push(i),this.groupButtons.push(a)});let r=document.createElement(`div`);if(r.className=`tcw-sidebar-spacer`,n.appendChild(r),n.appendChild(this.divider()),t.onToggleStyle){let e=document.createElement(`button`);e.className=`tcw-sidebar-btn`,e.title=`Drawing style & templates`,e.dataset.role=`style`,e.innerHTML=_(`palette`,14),e.addEventListener(`click`,t.onToggleStyle),n.appendChild(e)}this.magnetBtn=document.createElement(`button`),this.magnetBtn.className=`tcw-sidebar-btn`,this.magnetBtn.title=`Magnet`,this.magnetBtn.innerHTML=_(`magnet`,14),this.magnetBtn.addEventListener(`click`,t.onToggleMagnet),n.appendChild(this.magnetBtn);let i=document.createElement(`button`);i.className=`tcw-sidebar-btn`,i.title=`Undo`,i.innerHTML=_(`undo`,14),i.addEventListener(`click`,t.onUndo),n.appendChild(i);let a=document.createElement(`button`);a.className=`tcw-sidebar-btn`,a.title=`Redo`,a.innerHTML=_(`redo`,14),a.addEventListener(`click`,t.onRedo),n.appendChild(a);let o=document.createElement(`button`);o.className=`tcw-sidebar-btn tcw-danger`,o.title=`Clear all`,o.innerHTML=_(`trash`,14),o.addEventListener(`click`,t.onClearDrawings),n.appendChild(o)}setFavorites(e){this.favorites=[...e],this.renderFavorites()}renderFavorites(){if(!this.favoritesEl)return;this.favoritesEl.replaceChildren();let e=this.favorites.length>0;this.favoritesEl.style.display=e?``:`none`,this.favoritesDivider&&(this.favoritesDivider.style.display=e?``:`none`);for(let e of this.favorites){let t=document.createElement(`button`);t.className=`tcw-sidebar-btn`,t.title=`${re(this.config.drawingToolGroups,e)} (right-click to unpin)`,t.dataset.toolValue=e,t.innerHTML=_(ne(e),14),t.addEventListener(`click`,()=>this.callbacks.onDrawingTool(e)),t.addEventListener(`contextmenu`,t=>{t.preventDefault(),this.callbacks.onToggleFavorite?.(e)}),this.favoritesEl.appendChild(t)}}showFlyout(e){let t=this.config.drawingToolGroups[e];if(!t||t.tools.length<=1)return;this.hideFlyout();let n=document.createElement(`div`);n.className=`tcw-flyout`;let r=document.createElement(`div`);r.className=`tcw-flyout-header`,r.textContent=t.label,n.appendChild(r);for(let e of t.tools){let t=document.createElement(`button`);t.className=`tcw-flyout-item`,t.textContent=e.label,t.dataset.toolValue=e.value,t.addEventListener(`click`,()=>{this.callbacks.onDrawingTool(e.value),this.hideFlyout()}),this.callbacks.onToggleFavorite&&(this.favorites.includes(e.value)&&t.classList.add(`tcw-flyout-faved`),t.title=`Right-click to pin/unpin`,t.addEventListener(`contextmenu`,t=>{t.preventDefault(),this.callbacks.onToggleFavorite?.(e.value)})),n.appendChild(t)}this.flyoutEl=n,this.groupWraps[e].appendChild(n)}hideFlyout(){this.flyoutEl&&=(this.flyoutEl.remove(),null)}update(e){this.cursorBtn&&this.cursorBtn.classList.toggle(`tcw-active`,e.activeTool===null);let{drawingToolGroups:t}=this.config;for(let n=0;n<t.length;n++){let r=t[n].tools.some(t=>t.value===e.activeTool);this.groupButtons[n].classList.toggle(`tcw-active`,r)}this.flyoutEl&&this.flyoutEl.querySelectorAll(`.tcw-flyout-item`).forEach(t=>{let n=t;n.classList.toggle(`tcw-active`,n.dataset.toolValue===e.activeTool)}),this.magnetBtn&&(this.magnetBtn.classList.toggle(`tcw-active`,e.magnetEnabled),this.magnetBtn.title=e.magnetEnabled?`Magnet ON`:`Magnet OFF`)}divider(){let e=document.createElement(`div`);return e.className=`tcw-sidebar-divider`,e}destroy(){this.hideFlyout(),this.el.remove()}},ae=[`style`,`display`,`scale`],oe=class{callbacks;backdrop=null;modal=null;currentTab=`style`;currentSettings=null;bodyEl=null;tabButtons=[];constructor(e){this.callbacks=e}open(e){this.currentSettings={...e},this.currentTab=`style`,this.buildModal()}close(){this.backdrop?.remove(),this.modal?.remove(),this.backdrop=null,this.modal=null,this.bodyEl=null,this.tabButtons=[]}buildModal(){this.backdrop=document.createElement(`div`),this.backdrop.className=`tcw-modal-backdrop`,this.backdrop.addEventListener(`click`,()=>{this.callbacks.onClose(),this.close()}),document.body.appendChild(this.backdrop),this.modal=document.createElement(`div`),this.modal.className=`tcw-modal`;let e=document.createElement(`div`);e.className=`tcw-modal-header`;let t=document.createElement(`h3`);t.textContent=`Chart Settings`,e.appendChild(t);let n=document.createElement(`button`);n.className=`tcw-modal-close`,n.innerHTML=_(`x`,16),n.addEventListener(`click`,()=>{this.callbacks.onClose(),this.close()}),e.appendChild(n),this.modal.appendChild(e);let r=document.createElement(`div`);r.className=`tcw-modal-tabs`,this.tabButtons=[];for(let e of ae){let t=document.createElement(`button`);t.className=`tcw-modal-tab`,t.textContent=e,t.dataset.tab=e,e===this.currentTab&&t.classList.add(`tcw-active`),t.addEventListener(`click`,()=>{this.currentTab=e,this.tabButtons.forEach(t=>t.classList.toggle(`tcw-active`,t.dataset.tab===e)),this.renderTabContent()}),r.appendChild(t),this.tabButtons.push(t)}this.modal.appendChild(r),this.bodyEl=document.createElement(`div`),this.bodyEl.className=`tcw-modal-body`,this.modal.appendChild(this.bodyEl),this.renderTabContent();let i=document.createElement(`div`);i.className=`tcw-modal-footer`;let a=document.createElement(`button`);a.className=`tcw-reset-link`,a.textContent=`Reset to defaults`,a.addEventListener(`click`,()=>this.callbacks.onReset()),i.appendChild(a);let o=document.createElement(`button`);o.className=`tcw-done-btn`,o.textContent=`Done`,o.addEventListener(`click`,()=>{this.callbacks.onClose(),this.close()}),i.appendChild(o),this.modal.appendChild(i),document.body.appendChild(this.modal);let s=e=>{e.key===`Escape`&&(document.removeEventListener(`keydown`,s),this.callbacks.onClose(),this.close())};document.addEventListener(`keydown`,s)}renderTabContent(){if(!(!this.bodyEl||!this.currentSettings))switch(this.bodyEl.innerHTML=``,this.currentTab){case`style`:this.renderStyleTab();break;case`display`:this.renderDisplayTab();break;case`scale`:this.renderScaleTab();break}}renderStyleTab(){if(!this.bodyEl||!this.currentSettings)return;let e=this.currentSettings,t=this.section(`Candle Colors`);t.appendChild(this.colorRow(`Up Body`,e.candleUpColor,e=>this.patch({candleUpColor:e}))),t.appendChild(this.colorRow(`Down Body`,e.candleDownColor,e=>this.patch({candleDownColor:e}))),t.appendChild(this.colorRow(`Up Wick`,e.candleUpWick,e=>this.patch({candleUpWick:e}))),t.appendChild(this.colorRow(`Down Wick`,e.candleDownWick,e=>this.patch({candleDownWick:e}))),this.bodyEl.appendChild(t);let n=this.section(`Background`);n.appendChild(this.colorRow(`Background`,e.backgroundColor,e=>this.patch({backgroundColor:e}))),n.appendChild(this.colorRow(`Grid`,e.gridColor,e=>this.patch({gridColor:e}))),this.bodyEl.appendChild(n)}renderDisplayTab(){if(!this.bodyEl||!this.currentSettings)return;let e=this.currentSettings,t=this.section();t.appendChild(this.toggleRow(`Grid Lines`,e.gridVisible,e=>this.patch({gridVisible:e}))),t.appendChild(this.toggleRow(`Volume`,e.volumeVisible,e=>this.patch({volumeVisible:e}))),t.appendChild(this.toggleRow(`Volume Profile`,e.volumeProfileVisible,e=>this.patch({volumeProfileVisible:e}))),t.appendChild(this.toggleRow(`Market Profile (TPO)`,e.marketProfileVisible,e=>this.patch({marketProfileVisible:e}))),t.appendChild(this.toggleRow(`MP split by session`,e.marketProfileSplit,e=>this.patch({marketProfileSplit:e}))),t.appendChild(this.toggleRow(`MP letters (TPO)`,e.marketProfileLetters,e=>this.patch({marketProfileLetters:e}))),t.appendChild(this.rangeRow(`MP buckets`,e.marketProfileBuckets,8,200,1,e=>this.patch({marketProfileBuckets:e}))),t.appendChild(this.rangeRow(`MP opacity`,e.marketProfileOpacity,.05,1,.05,e=>this.patch({marketProfileOpacity:e}),e=>`${Math.round(e*100)}%`)),t.appendChild(this.toggleRow(`Liquidity heatmap`,e.depthHeatmapVisible,e=>this.patch({depthHeatmapVisible:e}))),t.appendChild(this.rangeRow(`Heatmap opacity`,e.depthHeatmapOpacity,.1,1,.05,e=>this.patch({depthHeatmapOpacity:e}),e=>`${Math.round(e*100)}%`)),t.appendChild(this.toggleRow(`Swing markers`,e.pivotMarkersVisible,e=>this.patch({pivotMarkersVisible:e}))),t.appendChild(this.rangeRow(`Swing strength`,e.pivotStrength,2,20,1,e=>this.patch({pivotStrength:e}))),t.appendChild(this.toggleRow(`Swing structure (HH/HL)`,e.pivotStructureLabels,e=>this.patch({pivotStructureLabels:e}))),t.appendChild(this.toggleRow(`Session shading (RTH)`,e.sessionShadingVisible,e=>this.patch({sessionShadingVisible:e}))),t.appendChild(this.toggleRow(`Prior-period levels`,e.periodLevelsVisible,e=>this.patch({periodLevelsVisible:e}))),t.appendChild(this.selectRow(`Period levels basis`,e.periodLevelsPeriod,[{value:`day`,label:`Prior Day (PDH/PDL)`},{value:`week`,label:`Prior Week (PWH/PWL)`}],e=>this.patch({periodLevelsPeriod:e}))),t.appendChild(this.toggleRow(`OHLC Legend`,e.legendVisible,e=>this.patch({legendVisible:e}))),t.appendChild(this.toggleRow(`Bar Countdown`,e.barCountdown,e=>this.patch({barCountdown:e}))),t.appendChild(this.selectRow(`Crosshair Mode`,e.crosshairMode,[{label:`Magnet`,value:`magnet`},{label:`Normal`,value:`normal`},{label:`Hidden`,value:`hidden`}],e=>this.patch({crosshairMode:e}))),t.appendChild(this.selectRow(`Timezone`,e.timezone,[{value:`local`,label:`Local`},{value:`0`,label:`UTC / London`},{value:`-300`,label:`New York (UTC-5)`},{value:`-360`,label:`Chicago (UTC-6)`},{value:`60`,label:`Frankfurt (UTC+1)`},{value:`480`,label:`Singapore/HK (UTC+8)`},{value:`540`,label:`Tokyo (UTC+9)`},{value:`330`,label:`Mumbai (UTC+5:30)`}],e=>this.patch({timezone:e}))),t.appendChild(this.selectRow(`Number Locale`,e.numberLocale,[{label:`en-US (65,234.00)`,value:`en-US`},{label:`de-DE (65.234,00)`,value:`de-DE`},{label:`fr-FR (65 234,00)`,value:`fr-FR`},{label:`vi-VN (65.234,00)`,value:`vi-VN`},{label:`en-IN (65,234.00)`,value:`en-IN`},{label:`ja-JP (65,234.00)`,value:`ja-JP`}],e=>this.patch({numberLocale:e}))),this.bodyEl.appendChild(t)}renderScaleTab(){if(!this.bodyEl||!this.currentSettings)return;let e=this.currentSettings,t=this.section();t.appendChild(this.toggleRow(`Auto Scale`,e.autoScale,e=>this.patch({autoScale:e}))),t.appendChild(this.selectRow(`Price Scale`,e.scaleMode,[{value:`regular`,label:`Regular`},{value:`logarithmic`,label:`Logarithmic`},{value:`percentage`,label:`Percentage`},{value:`indexedTo100`,label:`Indexed to 100`}],e=>this.patch({scaleMode:e}))),this.bodyEl.appendChild(t)}patch(e){this.currentSettings&&Object.assign(this.currentSettings,e),this.callbacks.onChange(e)}section(e){let t=document.createElement(`div`);if(t.className=`tcw-settings-section`,e){let n=document.createElement(`div`);n.className=`tcw-settings-section-title`,n.textContent=e,t.appendChild(n)}return t}colorRow(e,t,n){let r=document.createElement(`div`);r.className=`tcw-settings-row`;let i=document.createElement(`span`);i.className=`tcw-settings-label`,i.textContent=e,r.appendChild(i);let a=document.createElement(`div`);a.className=`tcw-color-picker-wrap`;let o=document.createElement(`input`);o.type=`color`,o.value=t;let s=document.createElement(`span`);return s.className=`tcw-color-hex`,s.textContent=t,o.addEventListener(`input`,()=>{s.textContent=o.value,n(o.value)}),a.appendChild(o),a.appendChild(s),r.appendChild(a),r}toggleRow(e,t,n){let r=document.createElement(`div`);r.className=`tcw-settings-row`;let i=document.createElement(`span`);i.className=`tcw-settings-label`,i.textContent=e,r.appendChild(i);let a=document.createElement(`button`);return a.className=`tcw-toggle${t?` tcw-on`:``}`,a.addEventListener(`click`,()=>{let e=!a.classList.contains(`tcw-on`);a.classList.toggle(`tcw-on`,e),n(e)}),r.appendChild(a),r}selectRow(e,t,n,r){let i=document.createElement(`div`);i.className=`tcw-settings-row`;let a=document.createElement(`span`);a.className=`tcw-settings-label`,a.textContent=e,i.appendChild(a);let o=document.createElement(`select`);o.className=`tcw-settings-select`;for(let e of n){let n=document.createElement(`option`);n.value=e.value,n.textContent=e.label,e.value===t&&(n.selected=!0),o.appendChild(n)}return o.addEventListener(`change`,()=>r(o.value)),i.appendChild(o),i}rangeRow(e,t,n,r,i,a,o=e=>String(e)){let s=document.createElement(`div`);s.className=`tcw-settings-row`;let c=document.createElement(`span`);c.className=`tcw-settings-label`,c.textContent=e,s.appendChild(c);let l=document.createElement(`div`);l.className=`tcw-settings-range`;let u=document.createElement(`input`);u.type=`range`,u.min=String(n),u.max=String(r),u.step=String(i),u.value=String(t);let d=document.createElement(`span`);return d.className=`tcw-settings-range-val`,d.textContent=o(t),u.addEventListener(`input`,()=>{let e=Number(u.value);d.textContent=o(e),a(e)}),l.appendChild(u),l.appendChild(d),s.appendChild(l),s}destroy(){this.close()}},b=class{el;dotEl;messageEl;infoEl;constructor(e){this.el=document.createElement(`div`),this.el.className=`tcw-statusbar`;let t=document.createElement(`div`);t.className=`tcw-status-indicator`,this.dotEl=document.createElement(`span`),this.dotEl.className=`tcw-status-dot`,t.appendChild(this.dotEl),this.messageEl=document.createElement(`span`),t.appendChild(this.messageEl),this.el.appendChild(t),this.infoEl=document.createElement(`span`),this.el.appendChild(this.infoEl),e.appendChild(this.el)}update(e){this.dotEl.className=`tcw-status-dot`,e.connectionState===`connected`?this.dotEl.classList.add(`tcw-connected`):e.connectionState===`error`&&this.dotEl.classList.add(`tcw-error`),this.messageEl.textContent=e.message,this.infoEl.textContent=`${e.symbol} ${e.timeframe}`}destroy(){this.el.remove()}},x=class{backdrop=null;modal=null;input=null;list=null;items=[];filtered=[];selectedIndex=0;callbacks;boundKeydown;constructor(e){this.callbacks=e,this.boundKeydown=this.handleKeydown.bind(this)}open(e){if(this.backdrop)return;this.items=e,this.filtered=e,this.selectedIndex=0,this.backdrop=document.createElement(`div`),this.backdrop.className=`tcw-modal-backdrop`,this.backdrop.addEventListener(`click`,()=>this.close()),this.modal=document.createElement(`div`),this.modal.className=`tcw-cmd-palette`;let t=document.createElement(`div`);t.className=`tcw-cmd-header`;let n=document.createElement(`span`);n.className=`tcw-cmd-icon`,n.textContent=`⌕`,t.appendChild(n),this.input=document.createElement(`input`),this.input.className=`tcw-cmd-input`,this.input.type=`text`,this.input.placeholder=`Search indicators, chart types, tools...`,this.input.addEventListener(`input`,()=>this.filter()),t.appendChild(this.input);let r=document.createElement(`span`);r.className=`tcw-cmd-hint`,r.textContent=`ESC`,t.appendChild(r),this.modal.appendChild(t),this.list=document.createElement(`div`),this.list.className=`tcw-cmd-list`,this.modal.appendChild(this.list);let i=document.createElement(`div`);i.className=`tcw-cmd-footer`,i.innerHTML=`<span>↑↓ Navigate</span><span>⏎ Select</span><span>Esc Close</span>`,this.modal.appendChild(i),document.body.appendChild(this.backdrop),document.body.appendChild(this.modal),this.renderList(),this.input.focus(),document.addEventListener(`keydown`,this.boundKeydown)}close(){document.removeEventListener(`keydown`,this.boundKeydown),this.backdrop?.remove(),this.modal?.remove(),this.backdrop=null,this.modal=null,this.input=null,this.list=null,this.callbacks.onClose()}isOpen(){return this.backdrop!==null}filter(){let e=this.input?.value.toLowerCase().trim()??``;e?this.filtered=this.items.filter(t=>t.label.toLowerCase().includes(e)||t.category.toLowerCase().includes(e)||t.id.toLowerCase().includes(e)):this.filtered=this.items,this.selectedIndex=0,this.renderList()}renderList(){if(!this.list)return;if(this.list.innerHTML=``,this.filtered.length===0){let e=document.createElement(`div`);e.className=`tcw-cmd-empty`,e.textContent=`No results found`,this.list.appendChild(e);return}let e=``;for(let t=0;t<this.filtered.length;t++){let n=this.filtered[t];if(n.category!==e){e=n.category;let t=document.createElement(`div`);t.className=`tcw-cmd-category`,t.textContent=this.categoryLabel(e),this.list.appendChild(t)}let r=document.createElement(`button`);r.className=`tcw-cmd-item`,t===this.selectedIndex&&r.classList.add(`tcw-selected`),n.active&&r.classList.add(`tcw-active`),r.dataset.index=String(t);let i=document.createElement(`span`);if(i.className=`tcw-cmd-item-label`,i.textContent=n.label,r.appendChild(i),n.active){let e=document.createElement(`span`);e.className=`tcw-cmd-check`,e.textContent=`✓`,r.appendChild(e)}if(n.shortcut){let e=document.createElement(`kbd`);e.className=`tcw-cmd-kbd`,e.textContent=n.shortcut,r.appendChild(e)}r.addEventListener(`click`,()=>this.select(t)),r.addEventListener(`mouseenter`,()=>{this.selectedIndex=t,this.updateSelection()}),this.list.appendChild(r)}}updateSelection(){if(!this.list)return;let e=this.list.querySelectorAll(`.tcw-cmd-item`);e.forEach((e,t)=>{e.classList.toggle(`tcw-selected`,t===this.selectedIndex)}),e[this.selectedIndex]?.scrollIntoView({block:`nearest`})}select(e){let t=this.filtered[e];if(t){switch(t.category){case`indicator`:this.callbacks.onIndicator(t.id);break;case`chartType`:this.callbacks.onChartType(t.id);break;case`drawing`:this.callbacks.onDrawingTool(t.id);break;case`timeframe`:this.callbacks.onTimeframe(t.id);break;case`action`:this.callbacks.onAction(t.id);break}this.close()}}handleKeydown(e){switch(e.key){case`Escape`:e.preventDefault(),this.close();break;case`ArrowDown`:e.preventDefault(),this.filtered.length>0&&(this.selectedIndex=(this.selectedIndex+1)%this.filtered.length,this.updateSelection());break;case`ArrowUp`:e.preventDefault(),this.filtered.length>0&&(this.selectedIndex=(this.selectedIndex-1+this.filtered.length)%this.filtered.length,this.updateSelection());break;case`Enter`:e.preventDefault(),this.select(this.selectedIndex);break}}categoryLabel(e){switch(e){case`indicator`:return`Indicators`;case`chartType`:return`Chart Types`;case`drawing`:return`Drawing Tools`;case`timeframe`:return`Timeframes`;case`action`:return`Actions`;default:return e}}destroy(){this.close()}},S=class{backdrop=null;modal=null;input=null;list=null;symbols=[];current=``;filtered=[];selectedIndex=0;callbacks;boundKeydown;pickOverride=null;constructor(e){this.callbacks=e,this.boundKeydown=this.handleKeydown.bind(this)}open(e,t,n){if(this.backdrop)return;this.pickOverride=n??null,this.symbols=e,this.current=t,this.filtered=e.map(e=>({symbol:e,score:0})),this.selectedIndex=Math.max(0,e.indexOf(t)),this.backdrop=document.createElement(`div`),this.backdrop.className=`tcw-modal-backdrop`,this.backdrop.addEventListener(`click`,()=>this.close()),this.modal=document.createElement(`div`),this.modal.className=`tcw-cmd-palette`;let r=document.createElement(`div`);r.className=`tcw-cmd-header`;let i=document.createElement(`span`);i.className=`tcw-cmd-icon`,i.innerHTML=E(),r.appendChild(i),this.input=document.createElement(`input`),this.input.className=`tcw-cmd-input`,this.input.type=`text`,this.input.placeholder=`Search symbol… (e.g. BTC, ETH, AAPL)`,this.input.autocomplete=`off`,this.input.spellcheck=!1,this.input.addEventListener(`input`,()=>this.filter()),r.appendChild(this.input);let a=document.createElement(`span`);a.className=`tcw-cmd-hint`,a.textContent=`ESC`,r.appendChild(a),this.modal.appendChild(r),this.list=document.createElement(`div`),this.list.className=`tcw-cmd-list`,this.modal.appendChild(this.list);let o=document.createElement(`div`);o.className=`tcw-cmd-footer`,o.innerHTML=`<span>↑↓ Navigate</span><span>⏎ Open</span><span>Esc Close</span>`,this.modal.appendChild(o),document.body.appendChild(this.backdrop),document.body.appendChild(this.modal),this.renderList(),this.input.focus(),document.addEventListener(`keydown`,this.boundKeydown)}close(){document.removeEventListener(`keydown`,this.boundKeydown),this.backdrop?.remove(),this.modal?.remove(),this.backdrop=null,this.modal=null,this.input=null,this.list=null,this.pickOverride=null,this.callbacks.onClose()}isOpen(){return this.backdrop!==null}destroy(){this.close()}filter(){let e=(this.input?.value??``).toUpperCase().trim();e?this.filtered=this.symbols.map(t=>({symbol:t,score:C(t.toUpperCase(),e)})).filter(e=>e.score>0).sort((e,t)=>t.score-e.score):this.filtered=this.symbols.map(e=>({symbol:e,score:0})),this.selectedIndex=0,this.renderList()}renderList(){if(!this.list)return;if(this.list.innerHTML=``,this.filtered.length===0){let e=document.createElement(`div`);e.className=`tcw-cmd-empty`,e.textContent=`No symbols match`,this.list.appendChild(e);return}let e=(this.input?.value??``).toUpperCase().trim();for(let t=0;t<this.filtered.length;t++){let{symbol:n}=this.filtered[t],r=document.createElement(`button`);r.className=`tcw-cmd-item`,t===this.selectedIndex&&r.classList.add(`tcw-selected`),n===this.current&&r.classList.add(`tcw-active`);let i=document.createElement(`span`);if(i.className=`tcw-cmd-item-label`,i.innerHTML=w(n,e),r.appendChild(i),n===this.current){let e=document.createElement(`span`);e.className=`tcw-cmd-check`,e.textContent=`✓`,r.appendChild(e)}r.addEventListener(`click`,()=>this.pick(t)),r.addEventListener(`mouseenter`,()=>{this.selectedIndex=t,this.updateSelection()}),this.list.appendChild(r)}}updateSelection(){if(!this.list)return;let e=this.list.querySelectorAll(`.tcw-cmd-item`);e.forEach((e,t)=>e.classList.toggle(`tcw-selected`,t===this.selectedIndex)),e[this.selectedIndex]?.scrollIntoView({block:`nearest`})}pick(e){let t=this.filtered[e];if(!t)return;let n=this.pickOverride;n?n(t.symbol):this.callbacks.onPick(t.symbol),this.close()}handleKeydown(e){switch(e.key){case`Escape`:e.preventDefault(),this.close();break;case`ArrowDown`:e.preventDefault(),this.filtered.length>0&&(this.selectedIndex=(this.selectedIndex+1)%this.filtered.length,this.updateSelection());break;case`ArrowUp`:e.preventDefault(),this.filtered.length>0&&(this.selectedIndex=(this.selectedIndex-1+this.filtered.length)%this.filtered.length,this.updateSelection());break;case`Enter`:e.preventDefault(),this.pick(this.selectedIndex);break}}};function C(e,t){if(e===t)return 1e3;if(e.startsWith(t))return 500+(50-Math.min(50,e.length-t.length));if(e.includes(t))return 200+(50-Math.min(50,e.length-t.length));let n=0,r=-1,i=0;for(let a=0;a<e.length&&n<t.length;a++)e[a]===t[n]&&(r>=0&&(i+=a-r-1),r=a,n++);return n<t.length?0:100-Math.min(99,i)}function w(e,t){if(!t)return T(e);let n=e.toUpperCase(),r=``,i=0;for(let a=0;a<e.length;a++)i<t.length&&n[a]===t[i]?(r+=`<mark style="background:transparent;color:var(--tcw-accent);font-weight:700">${T(e[a])}</mark>`,i++):r+=T(e[a]);return r}function T(e){return e.replace(/[&<>"']/g,e=>({"&":`&amp;`,"<":`&lt;`,">":`&gt;`,'"':`&quot;`,"'":`&#39;`})[e])}function E(){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>`}var D=typeof navigator<`u`&&/mac|iphone|ipad|ipod/i.test(navigator.platform||navigator.userAgent)?`⌘`:`Ctrl`,O=[{title:`Search & navigation`,entries:[{keys:[D,`K`],label:`Command palette`},{keys:[D,`P`],label:`Symbol search`},{keys:[`?`],label:`Show this sheet`}]},{title:`Chart manipulation`,entries:[{keys:[`Shift`,`Drag`],label:`Measure tool (bars × price Δ)`},{keys:[`Drag`,`Price axis`],label:`Compress / expand vertical scale`},{keys:[`Drag`,`Time axis`],label:`Zoom time axis`},{keys:[`Double-click`,`Price axis`],label:`Re-enable auto-scale`},{keys:[`Double-click`,`Time axis`],label:`Fit content`},{keys:[`Scroll`],label:`Zoom around cursor`}]},{title:`Touch (mobile / tablet)`,entries:[{keys:[`1 finger`,`Drag`],label:`Pan / move crosshair`},{keys:[`2 fingers`,`Pinch`],label:`Zoom around midpoint`},{keys:[`Long-press`],label:`Pin OHLC tooltip at bar`},{keys:[`Drag`,`Axis strip`],label:`Scale price / time axis`}]},{title:`Keyboard`,entries:[{keys:[`←`,`→`],label:`Pan one bar`},{keys:[`+`,`−`],label:`Zoom in / out`},{keys:[`Home`],label:`Scroll to start`},{keys:[`End`],label:`Scroll to end (live edge)`},{keys:[`F`],label:`Fit content`}]},{title:`Drawing`,entries:[{keys:[D,`Z`],label:`Undo`},{keys:[D,`Shift`,`Z`],label:`Redo`},{keys:[`Esc`],label:`Cancel active drawing`}]}],k=class{backdrop=null;modal=null;callbacks;boundKeydown;constructor(e){this.callbacks=e,this.boundKeydown=e=>{e.key===`Escape`&&(e.preventDefault(),this.close())}}open(){if(this.backdrop)return;this.backdrop=document.createElement(`div`),this.backdrop.className=`tcw-modal-backdrop`,this.backdrop.addEventListener(`click`,()=>this.close()),this.modal=document.createElement(`div`),this.modal.className=`tcw-modal tcw-hotkey-sheet`,this.modal.style.width=`640px`;let e=document.createElement(`div`);e.className=`tcw-modal-header`,e.innerHTML=`<h3>Keyboard shortcuts</h3>`;let t=document.createElement(`button`);t.className=`tcw-modal-close`,t.setAttribute(`aria-label`,`Close`),t.innerHTML=`×`,t.addEventListener(`click`,()=>this.close()),e.appendChild(t),this.modal.appendChild(e);let n=document.createElement(`div`);n.className=`tcw-modal-body`;let r=document.createElement(`div`);r.className=`tcw-hotkey-grid`;for(let e of O){let t=document.createElement(`section`);t.className=`tcw-hotkey-section`;let n=document.createElement(`div`);n.className=`tcw-settings-section-title`,n.textContent=e.title,t.appendChild(n);for(let n of e.entries){let e=document.createElement(`div`);e.className=`tcw-hotkey-row`;let r=document.createElement(`div`);r.className=`tcw-hotkey-keys`;for(let e=0;e<n.keys.length;e++){if(e>0){let e=document.createElement(`span`);e.className=`tcw-hotkey-sep`,e.textContent=`+`,r.appendChild(e)}let t=document.createElement(`kbd`);t.className=`tcw-cmd-kbd`,t.textContent=n.keys[e],r.appendChild(t)}e.appendChild(r);let i=document.createElement(`span`);i.className=`tcw-hotkey-label`,i.textContent=n.label,e.appendChild(i),t.appendChild(e)}r.appendChild(t)}n.appendChild(r),this.modal.appendChild(n);let i=document.createElement(`div`);i.className=`tcw-modal-footer`,i.innerHTML=`<span style="font-size:11px;color:var(--tcw-text-muted)">Press ? anytime to show this sheet</span>`;let a=document.createElement(`button`);a.className=`tcw-done-btn`,a.textContent=`Got it`,a.addEventListener(`click`,()=>this.close()),i.appendChild(a),this.modal.appendChild(i),document.body.appendChild(this.backdrop),document.body.appendChild(this.modal),document.addEventListener(`keydown`,this.boundKeydown)}close(){document.removeEventListener(`keydown`,this.boundKeydown),this.backdrop?.remove(),this.modal?.remove(),this.backdrop=null,this.modal=null,this.callbacks.onClose()}isOpen(){return this.backdrop!==null}destroy(){this.close()}},A=[.5,1,2,5,10,20,50,100],j=class{root=null;scrubber=null;progressLabel=null;playBtn=null;state=`stopped`;total=0;speed=5;callbacks;constructor(e){this.callbacks=e}mount(e,t){this.root||(this.total=Math.max(0,t.total),this.speed=t.speed??5,this.state=`paused`,this.root=document.createElement(`div`),this.root.className=`tcw-replay-bar`,this.root.innerHTML=this.markup(),e.appendChild(this.root),this.wireEvents(),this.syncUi())}unmount(){this.root?.remove(),this.root=null,this.scrubber=null,this.progressLabel=null,this.playBtn=null,this.state=`stopped`}isMounted(){return this.root!==null}setState(e){this.state=e,this.syncUi()}setProgress(e,t){this.total=t,this.scrubber&&(this.scrubber.max=String(Math.max(0,t-1)),this.scrubber.value=String(e)),this.progressLabel&&(this.progressLabel.textContent=`${e+1} / ${t}`)}destroy(){this.unmount()}markup(){let e=A.map(e=>`<option value="${e}"${e===this.speed?` selected`:``}>${e}× bars/s</option>`).join(``);return`
2380
+ <button class="tcw-replay-btn" data-act="close" title="Exit replay" aria-label="Exit replay">${I()}</button>
2381
+ <button class="tcw-replay-btn" data-act="stepBack" title="Step back" aria-label="Step back">${P()}</button>
2382
+ <button class="tcw-replay-btn tcw-replay-play" data-act="play" title="Play / pause" aria-label="Play / pause">${M()}</button>
2383
+ <button class="tcw-replay-btn" data-act="stepForward" title="Step forward" aria-label="Step forward">${F()}</button>
1452
2384
  <input type="range" class="tcw-replay-scrubber" data-act="seek" min="0" max="${Math.max(0,this.total-1)}" value="0" step="1" />
1453
2385
  <span class="tcw-replay-progress" data-tcw="progress">1 / ${this.total}</span>
1454
2386
  <select class="tcw-replay-speed" data-act="speed">${e}</select>
1455
- `}wireEvents(){this.root&&(this.scrubber=this.root.querySelector(`input[data-act="seek"]`),this.progressLabel=this.root.querySelector(`[data-tcw="progress"]`),this.playBtn=this.root.querySelector(`button[data-act="play"]`),this.root.querySelector(`[data-act="close"]`)?.addEventListener(`click`,()=>this.callbacks.onClose()),this.root.querySelector(`[data-act="stepBack"]`)?.addEventListener(`click`,()=>this.callbacks.onStepBack()),this.root.querySelector(`[data-act="stepForward"]`)?.addEventListener(`click`,()=>this.callbacks.onStepForward()),this.playBtn?.addEventListener(`click`,()=>{this.state===`playing`?this.callbacks.onPause():this.callbacks.onPlay()}),this.scrubber?.addEventListener(`input`,()=>{let e=Number(this.scrubber.value);this.callbacks.onSeek(e)}),this.root.querySelector(`[data-act="speed"]`)?.addEventListener(`change`,e=>{let t=Number(e.target.value);this.speed=t,this.callbacks.onSpeedChange(t)}))}syncUi(){this.playBtn&&(this.playBtn.innerHTML=this.state===`playing`?F():P(),this.playBtn.title=this.state===`playing`?`Pause`:`Play`)}};function P(){return`<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M8 5v14l11-7L8 5z"/></svg>`}function F(){return`<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M6 5h4v14H6zM14 5h4v14h-4z"/></svg>`}function I(){return`<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M6 6h2v12H6zM20 6L9 12l11 6V6z"/></svg>`}function L(){return`<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M4 6l11 6L4 18V6zM16 6h2v12h-2z"/></svg>`}function R(){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>`}var z=class{el;listEl;rowMap=new Map;entries=new Map;active=null;callbacks;constructor(e,t,n){this.callbacks=n,this.el=document.createElement(`div`),this.el.className=`tcw-watchlist`;let r=document.createElement(`div`);r.className=`tcw-watchlist-header`,r.textContent=`Watchlist`,this.el.appendChild(r),this.listEl=document.createElement(`div`),this.listEl.className=`tcw-watchlist-list`,this.el.appendChild(this.listEl);for(let e of t)this.entries.set(e,{symbol:e}),this.appendRow(e);e.appendChild(this.el)}setSymbols(e){let t=new Set(e);for(let e of this.rowMap.keys())t.has(e)||this.removeRow(e);for(let t of e)this.rowMap.has(t)||(this.entries.set(t,this.entries.get(t)??{symbol:t}),this.appendRow(t))}setActive(e){if(this.active===e)return;this.active&&this.rowMap.has(this.active)&&this.rowMap.get(this.active).row.classList.remove(`tcw-watchlist-active`),this.active=e;let t=this.rowMap.get(e);t&&t.row.classList.add(`tcw-watchlist-active`)}setEntry(e,t){let n={...this.entries.get(e)??{symbol:e},...t};this.entries.set(e,n),this.renderRow(e)}destroy(){this.el.remove(),this.rowMap.clear(),this.entries.clear()}appendRow(e){let t=document.createElement(`div`);t.className=`tcw-watchlist-row`,t.tabIndex=0;let n=document.createElement(`div`);n.className=`tcw-watchlist-symbol`,n.textContent=B(e);let r=document.createElement(`canvas`);r.className=`tcw-watchlist-spark`,r.width=64,r.height=22;let i=document.createElement(`div`);i.className=`tcw-watchlist-stats`;let a=document.createElement(`span`);a.className=`tcw-watchlist-price`,a.textContent=`—`;let o=document.createElement(`span`);o.className=`tcw-watchlist-change`,o.textContent=``,i.appendChild(a),i.appendChild(o),t.appendChild(n),t.appendChild(r),t.appendChild(i),t.addEventListener(`click`,()=>this.callbacks.onSelect(e)),t.addEventListener(`keydown`,t=>{(t.key===`Enter`||t.key===` `)&&(t.preventDefault(),this.callbacks.onSelect(e))}),this.listEl.appendChild(t),this.rowMap.set(e,{row:t,priceEl:a,changeEl:o,sparkCanvas:r}),e===this.active&&t.classList.add(`tcw-watchlist-active`)}removeRow(e){let t=this.rowMap.get(e);t&&(t.row.remove(),this.rowMap.delete(e))}renderRow(e){let t=this.rowMap.get(e),n=this.entries.get(e);if(!(!t||!n)){if(n.lastPrice!==void 0&&(t.priceEl.textContent=V(n.lastPrice)),n.lastPrice!==void 0&&n.refPrice!==void 0&&n.refPrice!==0){let e=n.lastPrice-n.refPrice,r=e/n.refPrice*100,i=e>=0?`+`:``;t.changeEl.textContent=`${i}${r.toFixed(2)}%`,t.changeEl.className=`tcw-watchlist-change ${e>=0?`tcw-up`:`tcw-down`}`}else t.changeEl.textContent=``;n.sparkline&&n.sparkline.length>=2&&H(t.sparkCanvas,n.sparkline,n.refPrice??n.sparkline[0])}}};function B(e){for(let t of[`USDT`,`USD`,`BTC`,`ETH`,`EUR`])if(e.length>t.length&&e.endsWith(t))return e.slice(0,-t.length)+`/`+t;return e}function V(e){if(e===0)return`0`;let t=Math.abs(e);return t>=1e3?e.toFixed(2):t>=1?e.toFixed(4):e.toPrecision(4)}function H(e,t,n){let r=e.getContext(`2d`);if(!r)return;let i=window.devicePixelRatio||1;e.width!==e.clientWidth*i&&(e.width=(e.clientWidth||64)*i,e.height=(e.clientHeight||22)*i);let a=e.width,o=e.height,s=1/0,c=-1/0;for(let e of t)e<s&&(s=e),e>c&&(c=e);let l=Math.max(c-s,1e-9),u=t[t.length-1]>=n?`#26a17b`:`#f23645`;r.clearRect(0,0,a,o),r.lineWidth=1.4*i,r.strokeStyle=u,r.beginPath();let d=a/(t.length-1);for(let e=0;e<t.length;e++){let n=e*d,i=o-(t[e]-s)/l*(o-4)-2;e===0?r.moveTo(n,i):r.lineTo(n,i)}r.stroke()}var U=class{chart;state;toolbar=null;sidebar=null;settings=null;statusBar=null;commandPalette=null;symbolSearch=null;hotkeySheet=null;replayBar=null;dragDrop=null;watchlist=null;watchlistSparkBuffer=new Map;sessionRefPrice=null;watchlistInterval=null;replayOriginalData=null;replayPollInterval=null;replaySpeed=5;layoutKeyPrefix=null;layoutDebounceMs=1500;activeLayoutKey=null;root;chartContainer;destroyed=!1;options;symbols;settingsState;adapter=null;boundGlobalKeydown=null;constructor(t,l={}){if(this.options=l,this.symbols=l.symbols??s,this.settingsState={...c},l.persistLayouts){let e=l.persistLayouts===!0?{}:l.persistLayouts;this.layoutKeyPrefix=e.keyPrefix??`tcw:layout:`,this.layoutDebounceMs=e.debounceMs??1500}let u=this.resolveIsDark(l.theme),d=this.resolveTheme(l.theme);this.state={symbol:l.symbol??this.symbols[0]??`BTCUSDT`,timeframe:l.timeframe??`5m`,chartType:l.chartOptions?.chartType??`candlestick`,isDark:u,activeIndicators:new Map,activeTool:null,magnetEnabled:!0,connectionState:`connecting`,connectionMessage:`Connecting...`},f(),this.root=document.createElement(`div`),this.root.className=`tcw-root`,this.root.dataset.tcwTheme=u?`dark`:`light`,t.appendChild(this.root),l.toolbar!==!1&&(this.toolbar=new _(this.root,{symbols:this.symbols,timeframes:l.timeframes?n.filter(e=>l.timeframes.includes(e.value)):n,chartTypes:l.chartTypes?r.filter(e=>l.chartTypes.includes(e.value)):r,indicators:a,popularIndicatorIds:o},{onSymbolClick:()=>this.handleSymbolClick(),onTimeframe:e=>this.handleTimeframe(e),onChartType:e=>this.handleChartType(e),onAddIndicator:e=>this.handleAddIndicator(e),onRemoveIndicator:e=>this.handleRemoveIndicator(e),onScreenshot:()=>this.chart.screenshot(),onSettings:()=>this.openSettings(),onToggleTheme:()=>this.handleToggleTheme(),onToggleReplay:()=>this.toggleReplay()}));let p=document.createElement(`div`);p.className=`tcw-body`,l.drawingTools!==!1&&(this.sidebar=new y(p,{drawingToolGroups:i},{onDrawingTool:e=>this.handleDrawingTool(e),onCancelDrawing:()=>this.handleCancelDrawing(),onToggleMagnet:()=>this.handleToggleMagnet(),onUndo:()=>this.chart.undo(),onRedo:()=>this.chart.redo(),onClearDrawings:()=>{this.chart.clearDrawings(),this.state={...this.state,activeTool:null},this.updateUI()}})),this.chartContainer=document.createElement(`div`),this.chartContainer.className=`tcw-chart-container`,p.appendChild(this.chartContainer),l.watchlist&&(this.watchlist=new z(p,this.symbols,{onSelect:e=>{this.setSymbol(e)}}),this.watchlist.setActive(this.state.symbol)),this.root.appendChild(p),this.chart=new e.r(this.chartContainer,{chartType:this.state.chartType,theme:d,autoScale:!0,crosshair:{mode:`magnet`},features:{drawings:!0,drawingMagnet:!0,drawingUndoRedo:!0,indicators:!0,trading:l.trading!==!1,tradingContextMenu:l.trading!==!1,volume:!0,legend:!0,crosshair:!0,keyboard:!0,screenshot:!0,alerts:!0,barCountdown:!0,logScale:!0,watermark:!0},...l.chartOptions}),l.dragDropImport!==!1&&(this.dragDrop=new e.t(this.chartContainer,{onData:(e,t,n)=>{this.chart.setData(e),this.toast(`Loaded ${t.data.length} bars from ${n.name}`+(t.skipped>0?` (${t.skipped} skipped)`:``))},onError:(e,t)=>{this.toast(`${t.name}: ${e.message}`,`error`)}}),this.dragDrop.attach()),l.statusBar!==!1&&(this.statusBar=new S(this.root)),l.settings!==!1&&(this.settings=new x({onChange:e=>this.applySettings(e),onReset:()=>this.resetSettings(),onClose:()=>{}})),this.symbolSearch=new w({onPick:e=>{this.setSymbol(e)},onClose:()=>{}}),this.hotkeySheet=new j({onClose:()=>{}}),this.commandPalette=new C({onIndicator:e=>this.handleAddIndicator(e),onChartType:e=>this.handleChartType(e),onDrawingTool:e=>this.handleDrawingTool(e),onTimeframe:e=>this.handleTimeframe(e),onAction:e=>this.handleAction(e),onClose:()=>{}}),this.boundGlobalKeydown=e=>{if((e.ctrlKey||e.metaKey)&&e.key===`k`)e.preventDefault(),this.toggleCommandPalette();else if((e.ctrlKey||e.metaKey)&&(e.key===`p`||e.key===`P`))e.preventDefault(),this.symbolSearch?.open(this.symbols,this.state.symbol);else if(e.key===`?`&&!e.ctrlKey&&!e.metaKey&&!e.altKey){let t=document.activeElement;if(t&&(t.tagName===`INPUT`||t.tagName===`TEXTAREA`||t.isContentEditable))return;e.preventDefault(),this.hotkeySheet?.open()}},document.addEventListener(`keydown`,this.boundGlobalKeydown),l.adapter&&(this.adapter=l.adapter,this.connectStream()),this.watchlist&&(this.watchlistInterval=setInterval(()=>this.tickWatchlist(),1e3)),this.updateUI(),l.onReady?.(this.chart)}setSymbols(e){this.symbols=e,this.watchlist?.setSymbols(e)}async setSymbol(e){this.flushActiveLayout(),this.state={...this.state,symbol:e},this.sessionRefPrice=null,this.options.onSymbolChange?.(e),this.updateUI(),this.watchlist?.setActive(e),this.adapter&&await this.connectStream()}setWatchlistEntry(e,t){this.watchlist?.setEntry(e,t)}tickWatchlist(){if(!this.watchlist)return;let e=this.chart.getData();if(e.length===0)return;let t=e[e.length-1];this.sessionRefPrice===null&&(this.sessionRefPrice=e[0].open);let n=this.watchlistSparkBuffer.get(this.state.symbol)??[];n.push(t.close),n.length>40&&n.shift(),this.watchlistSparkBuffer.set(this.state.symbol,n),this.watchlist.setEntry(this.state.symbol,{lastPrice:t.close,refPrice:this.sessionRefPrice,sparkline:n.slice()})}async setTimeframe(e){this.state={...this.state,timeframe:e},this.options.onTimeframeChange?.(e),this.updateUI(),this.adapter&&await this.connectStream()}setTheme(e){let t=this.resolveIsDark(e),n=this.resolveTheme(e);this.state={...this.state,isDark:t},this.root.dataset.tcwTheme=t?`dark`:`light`,this.chart.setTheme(n),this.updateUI()}getChart(){return this.chart}destroy(){this.destroyed||(this.destroyed=!0,this.boundGlobalKeydown&&document.removeEventListener(`keydown`,this.boundGlobalKeydown),this.flushActiveLayout(),this.commandPalette?.destroy(),this.symbolSearch?.destroy(),this.hotkeySheet?.destroy(),this.replayPollInterval&&clearInterval(this.replayPollInterval),this.replayBar?.destroy(),this.dragDrop?.detach(),this.watchlistInterval&&clearInterval(this.watchlistInterval),this.watchlist?.destroy(),this.toolbar?.destroy(),this.sidebar?.destroy(),this.settings?.destroy(),this.statusBar?.destroy(),this.chart.destroy(),this.root.remove(),p())}handleSymbolClick(){this.symbolSearch?.open(this.symbols,this.state.symbol)}handleTimeframe(e){this.state={...this.state,timeframe:e},this.options.onTimeframeChange?.(e),this.updateUI(),this.adapter&&this.connectStream()}handleChartType(e){this.state={...this.state,chartType:e},this.chart.setChartType(e),this.updateUI()}handleAddIndicator(e){if(this.state.activeIndicators.has(e)){let t=this.state.activeIndicators.get(e);this.chart.removeIndicator(t);let n=new Map(this.state.activeIndicators);n.delete(e),this.state={...this.state,activeIndicators:n}}else{let t=this.chart.addIndicator(e);if(t){let n=new Map(this.state.activeIndicators);n.set(e,t),this.state={...this.state,activeIndicators:n}}}this.updateUI()}handleRemoveIndicator(e){this.chart.removeIndicator(e);let t=new Map(this.state.activeIndicators);for(let[n,r]of t.entries())if(r===e){t.delete(n);break}this.state={...this.state,activeIndicators:t},this.updateUI()}toggleCommandPalette(){if(this.commandPalette?.isOpen()){this.commandPalette.close();return}this.commandPalette?.open(this.buildCommandItems())}buildCommandItems(){let e=[];for(let t of a)e.push({id:t.id,label:t.name,category:`indicator`,active:this.state.activeIndicators.has(t.id)});for(let t of r)e.push({id:t.value,label:t.label,category:`chartType`,active:this.state.chartType===t.value});for(let t of i)for(let n of t.tools)e.push({id:n.value,label:n.label,category:`drawing`,active:this.state.activeTool===n.value});for(let t of n)e.push({id:t.value,label:t.label,category:`timeframe`,active:this.state.timeframe===t.value});return e.push({id:`screenshot`,label:`Screenshot`,category:`action`,shortcut:``},{id:`toggleTheme`,label:`Toggle Theme`,category:`action`},{id:`settings`,label:`Settings`,category:`action`},{id:`clearDrawings`,label:`Clear All Drawings`,category:`action`}),e}handleAction(e){switch(e){case`screenshot`:this.chart.screenshot();break;case`toggleTheme`:this.handleToggleTheme();break;case`settings`:this.openSettings();break;case`clearDrawings`:this.chart.clearDrawings(),this.state={...this.state,activeTool:null},this.updateUI();break}}handleDrawingTool(e){this.state={...this.state,activeTool:e},this.chart.setDrawingTool(e),this.updateUI()}handleCancelDrawing(){this.state={...this.state,activeTool:null},this.chart.setDrawingTool(null),this.updateUI()}handleToggleMagnet(){let e=!this.state.magnetEnabled;this.state={...this.state,magnetEnabled:e},this.chart.setDrawingMagnet(e),this.updateUI()}handleToggleTheme(){let e=!this.state.isDark;this.state={...this.state,isDark:e},this.root.dataset.tcwTheme=e?`dark`:`light`,this.chart.setTheme(e?t.DARK_THEME:t.LIGHT_THEME),this.chart.setWatermark(this.state.symbol.replace(`USDT`,` / USDT`),{fontSize:48,color:e?`rgba(255,255,255,0.03)`:`rgba(0,0,0,0.03)`}),this.updateUI()}openSettings(){this.settings?.open(this.settingsState)}toast(e,t=`info`){let n=document.createElement(`div`);n.className=`tcw-toast ${t===`error`?`tcw-toast-error`:``}`,n.textContent=e,this.root.appendChild(n),requestAnimationFrame(()=>n.classList.add(`tcw-toast-in`)),setTimeout(()=>{n.classList.remove(`tcw-toast-in`),n.addEventListener(`transitionend`,()=>n.remove(),{once:!0}),setTimeout(()=>n.remove(),400)},3500)}clearSavedLayout(e){if(!this.layoutKeyPrefix)return;let t=e??this.state.symbol;try{localStorage.removeItem(this.layoutKeyPrefix+t)}catch{}}applySymbolLayout(e){if(!this.layoutKeyPrefix)return;let t=this.layoutKeyPrefix+e;this.activeLayoutKey=t;try{this.chart.loadStateFromStorage(t)&&this.rebuildActiveIndicatorsMapFromChart()}catch{}this.chart.setAutoSave(t,this.layoutDebounceMs)}flushActiveLayout(){if(this.activeLayoutKey){try{this.chart.saveState(this.activeLayoutKey)}catch{}this.chart.disableAutoSave(),this.activeLayoutKey=null}}rebuildActiveIndicatorsMapFromChart(){let e=new Map;for(let t of this.chart.getActiveIndicators())e.set(t.id,t.instanceId);this.state={...this.state,activeIndicators:e},this.updateUI()}toggleReplay(){this.replayBar?.isMounted()?this.exitReplay():this.enterReplay()}enterReplay(){let e=this.chart.getData();e.length<2||(this.replayOriginalData=e.slice(),this.replayBar=new N({onPlay:()=>{this.chart.getReplayState()===`paused`?this.chart.replayResume():this.chart.replay({speed:this.replaySpeed,interval:200}),this.replayBar?.setState(`playing`)},onPause:()=>{this.chart.replayPause(),this.replayBar?.setState(`paused`)},onStop:()=>{this.chart.replayStop(),this.replayBar?.setState(`paused`)},onStepBack:()=>{let e=this.chart.getReplayProgress();this.chart.getReplayState()===`playing`&&this.chart.replayPause(),this.chart.replaySeek(Math.max(0,e.current-1)),this.replayBar?.setState(`paused`)},onStepForward:()=>{let e=this.chart.getReplayProgress();this.chart.getReplayState()===`playing`&&this.chart.replayPause(),this.chart.replaySeek(Math.min(e.total-1,e.current+1)),this.replayBar?.setState(`paused`)},onSeek:e=>{this.chart.getReplayState()===`playing`&&this.chart.replayPause(),this.chart.replaySeek(e),this.replayBar?.setState(`paused`)},onSpeedChange:e=>{this.replaySpeed=e,this.chart.setReplaySpeed(e)},onClose:()=>this.exitReplay()}),this.replayBar.mount(this.chartContainer,{total:e.length,speed:this.replaySpeed}),this.chart.replay({speed:this.replaySpeed,interval:200,startIndex:1}),this.chart.replayPause(),this.replayBar.setState(`paused`),this.replayPollInterval=setInterval(()=>{if(!this.replayBar?.isMounted())return;let e=this.chart.getReplayProgress();this.replayBar.setProgress(e.current,e.total);let t=this.chart.getReplayState();t===`stopped`?this.replayBar.setState(`paused`):this.replayBar.setState(t)},150))}exitReplay(){this.replayPollInterval&&=(clearInterval(this.replayPollInterval),null),this.chart.replayStop(),this.replayBar?.unmount(),this.replayBar=null,this.replayOriginalData&&=(this.chart.setData(this.replayOriginalData),null)}applySettings(e){this.settingsState={...this.settingsState,...e},e.gridVisible!==void 0&&this.chart.setGridVisible(e.gridVisible),e.volumeVisible!==void 0&&this.chart.setVolumeVisible(e.volumeVisible),e.volumeProfileVisible!==void 0&&this.chart.setVolumeProfileVisible(e.volumeProfileVisible),e.crosshairMode!==void 0&&this.chart.setCrosshairMode(e.crosshairMode),e.autoScale!==void 0&&this.chart.setAutoScale(e.autoScale),e.logScale!==void 0&&this.chart.setLogScale(e.logScale),e.numberLocale!==void 0&&this.chart.setNumberLocale(e.numberLocale);let t={...this.chart.getTheme()},n=!1;e.candleUpColor!==void 0&&(t.candleUp=e.candleUpColor,n=!0),e.candleDownColor!==void 0&&(t.candleDown=e.candleDownColor,n=!0),e.candleUpWick!==void 0&&(t.candleUpWick=e.candleUpWick,n=!0),e.candleDownWick!==void 0&&(t.candleDownWick=e.candleDownWick,n=!0),e.backgroundColor!==void 0&&(t.background=e.backgroundColor,n=!0),e.gridColor!==void 0&&(t.grid=e.gridColor,n=!0),n&&this.chart.setTheme(t)}resetSettings(){this.settingsState={...c},this.applySettings(this.settingsState)}async connectStream(){if(this.adapter){this.state={...this.state,connectionState:`connecting`,connectionMessage:`Connecting...`},this.updateUI();try{this.chart.disconnectStream(),await this.chart.connect({adapter:this.adapter,symbol:this.state.symbol,timeframe:this.state.timeframe,historyLimit:this.options.historyLimit??500}),this.chart.setWatermark(this.state.symbol.replace(`USDT`,` / USDT`),{fontSize:48,color:this.state.isDark?`rgba(255,255,255,0.03)`:`rgba(0,0,0,0.03)`}),this.applySymbolLayout(this.state.symbol),this.state={...this.state,connectionState:`connected`,connectionMessage:`Live`}}catch(e){this.state={...this.state,connectionState:`error`,connectionMessage:e instanceof Error?e.message:`Connection failed`}}this.updateUI()}}updateUI(){this.toolbar?.update(this.state),this.sidebar?.update(this.state),this.statusBar?.update({connectionState:this.state.connectionState,message:this.state.connectionMessage,symbol:this.state.symbol,timeframe:this.state.timeframe})}resolveIsDark(e){return e===void 0||e===`dark`?!0:e===`light`?!1:typeof e==`object`&&e.background?this.isColorDark(e.background):!0}resolveTheme(e){return e===void 0||e===`dark`?t.DARK_THEME:e===`light`?t.LIGHT_THEME:typeof e==`object`?e:t.DARK_THEME}isColorDark(e){if(e.startsWith(`#`)&&e.length>=7){let t=parseInt(e.slice(1,3),16),n=parseInt(e.slice(3,5),16),r=parseInt(e.slice(5,7),16);return t+n+r<384}return!0}};exports.ChartWidget=U;
2387
+ `}wireEvents(){this.root&&(this.scrubber=this.root.querySelector(`input[data-act="seek"]`),this.progressLabel=this.root.querySelector(`[data-tcw="progress"]`),this.playBtn=this.root.querySelector(`button[data-act="play"]`),this.root.querySelector(`[data-act="close"]`)?.addEventListener(`click`,()=>this.callbacks.onClose()),this.root.querySelector(`[data-act="stepBack"]`)?.addEventListener(`click`,()=>this.callbacks.onStepBack()),this.root.querySelector(`[data-act="stepForward"]`)?.addEventListener(`click`,()=>this.callbacks.onStepForward()),this.playBtn?.addEventListener(`click`,()=>{this.state===`playing`?this.callbacks.onPause():this.callbacks.onPlay()}),this.scrubber?.addEventListener(`input`,()=>{let e=Number(this.scrubber.value);this.callbacks.onSeek(e)}),this.root.querySelector(`[data-act="speed"]`)?.addEventListener(`change`,e=>{let t=Number(e.target.value);this.speed=t,this.callbacks.onSpeedChange(t)}))}syncUi(){this.playBtn&&(this.playBtn.innerHTML=this.state===`playing`?N():M(),this.playBtn.title=this.state===`playing`?`Pause`:`Play`)}};function M(){return`<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M8 5v14l11-7L8 5z"/></svg>`}function N(){return`<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M6 5h4v14H6zM14 5h4v14h-4z"/></svg>`}function P(){return`<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M6 6h2v12H6zM20 6L9 12l11 6V6z"/></svg>`}function F(){return`<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M4 6l11 6L4 18V6zM16 6h2v12h-2z"/></svg>`}function I(){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>`}var L=class{el;listEl;rowMap=new Map;entries=new Map;active=null;callbacks;constructor(e,t,n){this.callbacks=n,this.el=document.createElement(`div`),this.el.className=`tcw-watchlist`;let r=document.createElement(`div`);r.className=`tcw-watchlist-header`,r.textContent=`Watchlist`,this.el.appendChild(r),this.listEl=document.createElement(`div`),this.listEl.className=`tcw-watchlist-list`,this.el.appendChild(this.listEl);for(let e of t)this.entries.set(e,{symbol:e}),this.appendRow(e);e.appendChild(this.el)}setSymbols(e){let t=new Set(e);for(let e of this.rowMap.keys())t.has(e)||this.removeRow(e);for(let t of e)this.rowMap.has(t)||(this.entries.set(t,this.entries.get(t)??{symbol:t}),this.appendRow(t))}setActive(e){if(this.active===e)return;this.active&&this.rowMap.has(this.active)&&this.rowMap.get(this.active).row.classList.remove(`tcw-watchlist-active`),this.active=e;let t=this.rowMap.get(e);t&&t.row.classList.add(`tcw-watchlist-active`)}setEntry(e,t){let n={...this.entries.get(e)??{symbol:e},...t};this.entries.set(e,n),this.renderRow(e)}destroy(){this.el.remove(),this.rowMap.clear(),this.entries.clear()}appendRow(e){let t=document.createElement(`div`);t.className=`tcw-watchlist-row`,t.tabIndex=0;let n=document.createElement(`div`);n.className=`tcw-watchlist-symbol`,n.textContent=R(e);let r=document.createElement(`canvas`);r.className=`tcw-watchlist-spark`,r.width=64,r.height=22;let i=document.createElement(`div`);i.className=`tcw-watchlist-stats`;let a=document.createElement(`span`);a.className=`tcw-watchlist-price`,a.textContent=`—`;let o=document.createElement(`span`);o.className=`tcw-watchlist-change`,o.textContent=``,i.appendChild(a),i.appendChild(o),t.appendChild(n),t.appendChild(r),t.appendChild(i),t.addEventListener(`click`,()=>this.callbacks.onSelect(e)),t.addEventListener(`keydown`,t=>{(t.key===`Enter`||t.key===` `)&&(t.preventDefault(),this.callbacks.onSelect(e))}),this.listEl.appendChild(t),this.rowMap.set(e,{row:t,priceEl:a,changeEl:o,sparkCanvas:r}),e===this.active&&t.classList.add(`tcw-watchlist-active`)}removeRow(e){let t=this.rowMap.get(e);t&&(t.row.remove(),this.rowMap.delete(e))}renderRow(e){let t=this.rowMap.get(e),n=this.entries.get(e);if(!(!t||!n)){if(n.lastPrice!==void 0&&(t.priceEl.textContent=z(n.lastPrice)),n.lastPrice!==void 0&&n.refPrice!==void 0&&n.refPrice!==0){let e=n.lastPrice-n.refPrice,r=e/n.refPrice*100,i=e>=0?`+`:``;t.changeEl.textContent=`${i}${r.toFixed(2)}%`,t.changeEl.className=`tcw-watchlist-change ${e>=0?`tcw-up`:`tcw-down`}`}else t.changeEl.textContent=``;n.sparkline&&n.sparkline.length>=2&&B(t.sparkCanvas,n.sparkline,n.refPrice??n.sparkline[0])}}};function R(e){for(let t of[`USDT`,`USD`,`BTC`,`ETH`,`EUR`])if(e.length>t.length&&e.endsWith(t))return e.slice(0,-t.length)+`/`+t;return e}function z(e){if(e===0)return`0`;let t=Math.abs(e);return t>=1e3?e.toFixed(2):t>=1?e.toFixed(4):e.toPrecision(4)}function B(e,t,n){let r=e.getContext(`2d`);if(!r)return;let i=window.devicePixelRatio||1;e.width!==e.clientWidth*i&&(e.width=(e.clientWidth||64)*i,e.height=(e.clientHeight||22)*i);let a=e.width,o=e.height,s=1/0,c=-1/0;for(let e of t)e<s&&(s=e),e>c&&(c=e);let l=Math.max(c-s,1e-9),u=t[t.length-1]>=n?`#26a17b`:`#f23645`;r.clearRect(0,0,a,o),r.lineWidth=1.4*i,r.strokeStyle=u,r.beginPath();let d=a/(t.length-1);for(let e=0;e<t.length;e++){let n=e*d,i=o-(t[e]-s)/l*(o-4)-2;e===0?r.moveTo(n,i):r.lineTo(n,i)}r.stroke()}var V=[{value:`crossing`,label:`Crossing`},{value:`crossingUp`,label:`Crossing up`},{value:`crossingDown`,label:`Crossing down`},{value:`greaterThan`,label:`Greater than`},{value:`lessThan`,label:`Less than`}],H=new Map(V.map(e=>[e.value,e.label]));function U(e){return Math.round(e*1e6)/1e6}function W(e){let t=Math.abs(e);return t>=1e3||t>=1?e.toFixed(2):e.toPrecision(4)}var G=class{el;listEl;priceInput;conditionSelect;sourceSelect;messageInput;emptyEl;callbacks;open=!1;alerts=[];sources=[{channel:`price`,label:`Price`}];constructor(e,t){this.callbacks=t,this.el=document.createElement(`div`),this.el.className=`tcw-alerts-panel`,this.el.hidden=!0;let n=document.createElement(`div`);n.className=`tcw-alerts-header`;let r=document.createElement(`span`);r.textContent=`Price Alerts`;let i=document.createElement(`button`);i.className=`tcw-alerts-close`,i.type=`button`,i.setAttribute(`aria-label`,`Close alerts`),i.innerHTML=_(`x`,14),i.addEventListener(`click`,()=>this.close()),n.appendChild(r),n.appendChild(i),this.el.appendChild(n);let a=document.createElement(`form`);a.className=`tcw-alerts-form`,this.sourceSelect=document.createElement(`select`),this.sourceSelect.className=`tcw-alerts-source`,this.sourceSelect.addEventListener(`change`,()=>this.prefillPrice()),this.priceInput=document.createElement(`input`),this.priceInput.type=`number`,this.priceInput.step=`any`,this.priceInput.placeholder=`Value`,this.priceInput.className=`tcw-alerts-price`,this.priceInput.required=!0,this.conditionSelect=document.createElement(`select`),this.conditionSelect.className=`tcw-alerts-condition`;for(let e of V){let t=document.createElement(`option`);t.value=e.value,t.textContent=e.label,this.conditionSelect.appendChild(t)}this.messageInput=document.createElement(`input`),this.messageInput.type=`text`,this.messageInput.placeholder=`Note (optional)`,this.messageInput.className=`tcw-alerts-message`;let o=document.createElement(`button`);o.type=`submit`,o.className=`tcw-alerts-add`,o.innerHTML=`${_(`plus`,14)}<span>Add alert</span>`,a.appendChild(this.sourceSelect),a.appendChild(this.priceInput),a.appendChild(this.conditionSelect),a.appendChild(this.messageInput),a.appendChild(o),a.addEventListener(`submit`,e=>{e.preventDefault(),this.submitForm()}),this.el.appendChild(a),this.listEl=document.createElement(`div`),this.listEl.className=`tcw-alerts-list`,this.el.appendChild(this.listEl),this.emptyEl=document.createElement(`div`),this.emptyEl.className=`tcw-alerts-empty`,this.emptyEl.textContent=`No alerts yet. Add one above, or right-click the chart.`,this.listEl.appendChild(this.emptyEl),this.renderSources(),e.appendChild(this.el)}setSources(e){this.sources=e.length>0?e:[{channel:`price`,label:`Price`}],this.renderSources()}renderSources(){let e=this.sourceSelect.value||`price`;this.sourceSelect.replaceChildren();for(let e of this.sources){let t=document.createElement(`option`);t.value=e.channel,t.textContent=e.label,this.sourceSelect.appendChild(t)}this.sourceSelect.value=this.sources.some(t=>t.channel===e)?e:`price`}isOpen(){return this.open}toggle(){this.open?this.close():this.openPanel()}openPanel(){this.open=!0,this.el.hidden=!1,this.priceInput.value===``&&this.prefillPrice()}prefillPrice(){let e=this.callbacks.getChannelValue(this.sourceSelect.value||`price`);this.priceInput.value=e===null?``:String(U(e))}close(){this.open=!1,this.el.hidden=!0}setAlerts(e){this.alerts=e,this.renderList()}destroy(){this.el.remove()}submitForm(){let e=Number(this.priceInput.value);if(!Number.isFinite(e))return;let t=this.conditionSelect.value,n=this.messageInput.value.trim()||void 0,r=this.sourceSelect.value||`price`,i=this.sources.find(e=>e.channel===r)?.label??`Price`;this.callbacks.onAdd(e,t,n,r,i),this.messageInput.value=``,this.prefillPrice()}renderList(){if(this.listEl.replaceChildren(),this.alerts.length===0){this.listEl.appendChild(this.emptyEl);return}for(let e of[...this.alerts].reverse()){let t=document.createElement(`div`);t.className=`tcw-alerts-row`+(e.triggered?` tcw-alerts-triggered`:``);let n=document.createElement(`div`);n.className=`tcw-alerts-info`;let r=document.createElement(`div`);r.className=`tcw-alerts-row-main`;let i=H.get(e.condition)??e.condition,a=e.channel&&e.channel!==`price`,o=a?W(e.price):this.callbacks.formatPrice(e.price);if(r.textContent=`${a&&e.label?`${e.label} `:``}${i} ${o}`,n.appendChild(r),e.message){let t=document.createElement(`div`);t.className=`tcw-alerts-row-note`,t.textContent=e.message,n.appendChild(t)}if(e.triggered){let e=document.createElement(`span`);e.className=`tcw-alerts-badge`,e.textContent=`triggered`,r.appendChild(e)}let s=document.createElement(`button`);s.type=`button`,s.className=`tcw-alerts-del`,s.setAttribute(`aria-label`,`Delete alert`),s.innerHTML=_(`trash`,14),s.addEventListener(`click`,()=>this.callbacks.onRemove(e.id)),t.appendChild(n),t.appendChild(s),this.listEl.appendChild(t)}}},K=class{el;indicatorsEl;drawingsEl;compareEl=null;callbacks;open=!1;constructor(e,t){this.callbacks=t,this.el=document.createElement(`div`),this.el.className=`tcw-tree-panel`,this.el.hidden=!0;let n=document.createElement(`div`);n.className=`tcw-tree-header`;let r=document.createElement(`span`);r.textContent=`Objects`;let i=document.createElement(`button`);i.type=`button`,i.className=`tcw-tree-close`,i.setAttribute(`aria-label`,`Close objects`),i.innerHTML=_(`x`,14),i.addEventListener(`click`,()=>this.close()),n.appendChild(r),n.appendChild(i),this.el.appendChild(n),this.indicatorsEl=this.makeSection(`Indicators`),this.drawingsEl=this.makeSection(`Drawings`),this.callbacks.onAddCompare&&(this.compareEl=this.makeSection(`Compare`,()=>this.callbacks.onAddCompare?.())),e.appendChild(this.el)}isOpen(){return this.open}toggle(){this.open?this.close():this.openPanel()}openPanel(){this.open=!0,this.el.hidden=!1}close(){this.open=!1,this.el.hidden=!0}destroy(){this.el.remove()}setObjects(e,t,n=[]){this.renderIndicators(e),this.renderDrawings(t),this.renderCompares(n)}makeSection(e,t){let n=document.createElement(`div`);n.className=`tcw-tree-section`;let r=document.createElement(`div`);r.className=`tcw-tree-section-head`;let i=document.createElement(`span`);if(i.textContent=e,r.appendChild(i),t){let n=document.createElement(`button`);n.type=`button`,n.className=`tcw-tree-add`,n.setAttribute(`aria-label`,`Add ${e.toLowerCase()}`),n.title=`Add ${e.toLowerCase()}`,n.innerHTML=_(`plus`,13),n.addEventListener(`click`,t),r.appendChild(n)}let a=document.createElement(`div`);return a.className=`tcw-tree-list`,n.appendChild(r),n.appendChild(a),this.el.appendChild(n),a}renderIndicators(e){if(this.indicatorsEl.replaceChildren(),e.length===0){this.indicatorsEl.appendChild(this.emptyRow(`No indicators`));return}for(let t of e){let e=this.row(t.name);t.visible||e.classList.add(`tcw-tree-hidden`);let n=document.createElement(`div`);n.className=`tcw-tree-actions`,this.callbacks.onToggleIndicatorVisible&&n.appendChild(this.iconButton(t.visible?`eye`:`eyeOff`,t.visible?`Hide`:`Show`,``,()=>this.callbacks.onToggleIndicatorVisible?.(t.instanceId,!t.visible))),this.callbacks.onConfigureIndicator&&n.appendChild(this.iconButton(`settings`,`Indicator settings`,``,()=>this.callbacks.onConfigureIndicator?.(t.instanceId))),n.appendChild(this.iconButton(`trash`,`Remove indicator`,`tcw-tree-del`,()=>this.callbacks.onRemoveIndicator(t.instanceId))),e.appendChild(n),this.indicatorsEl.appendChild(e)}}renderDrawings(e){if(this.drawingsEl.replaceChildren(),e.length===0){this.drawingsEl.appendChild(this.emptyRow(`No drawings`));return}for(let t of e){let e=this.row(t.label);t.visible||e.classList.add(`tcw-tree-hidden`);let n=document.createElement(`div`);n.className=`tcw-tree-actions`,n.appendChild(this.iconButton(t.visible?`eye`:`eyeOff`,t.visible?`Hide`:`Show`,``,()=>this.callbacks.onToggleDrawingVisible(t.id,!t.visible))),n.appendChild(this.iconButton(t.locked?`lock`:`unlock`,t.locked?`Unlock`:`Lock`,t.locked?`tcw-tree-on`:``,()=>this.callbacks.onToggleDrawingLocked(t.id,!t.locked))),n.appendChild(this.iconButton(`trash`,`Remove drawing`,`tcw-tree-del`,()=>this.callbacks.onRemoveDrawing(t.id))),e.appendChild(n),this.drawingsEl.appendChild(e)}}renderCompares(e){if(this.compareEl){if(this.compareEl.replaceChildren(),e.length===0){this.compareEl.appendChild(this.emptyRow(`No comparisons`));return}for(let t of e){let e=this.row(t.label),n=document.createElement(`span`);n.className=`tcw-tree-dot`,n.style.background=t.color,e.insertBefore(n,e.firstChild),this.callbacks.onRemoveCompare&&e.appendChild(this.iconButton(`trash`,`Remove comparison`,`tcw-tree-del`,()=>this.callbacks.onRemoveCompare?.(t.id))),this.compareEl.appendChild(e)}}}row(e){let t=document.createElement(`div`);t.className=`tcw-tree-row`;let n=document.createElement(`span`);return n.className=`tcw-tree-name`,n.textContent=e,n.title=e,t.appendChild(n),t}emptyRow(e){let t=document.createElement(`div`);return t.className=`tcw-tree-empty`,t.textContent=e,t}iconButton(e,t,n,r){let i=document.createElement(`button`);return i.type=`button`,i.className=`tcw-tree-btn ${n}`.trim(),i.setAttribute(`aria-label`,t),i.title=t,i.innerHTML=_(e,14),i.addEventListener(`click`,r),i}},q={trendLine:`Trend Line`,ray:`Ray`,extendedLine:`Extended Line`,horizontalLine:`Horizontal Line`,verticalLine:`Vertical Line`,rectangle:`Rectangle`,ellipse:`Ellipse`,triangle:`Triangle`,arrow:`Arrow`,parallelChannel:`Parallel Channel`,regressionChannel:`Regression Channel`,pitchfork:`Pitchfork`,fibRetracement:`Fib Retracement`,fibExtension:`Fib Extension`,fibTimeZones:`Fib Time Zones`,gannBox:`Gann Box`,gannFan:`Gann Fan`,elliottWave:`Elliott Wave`,priceRange:`Price Range`,dateRange:`Date Range`,measure:`Measure`,textAnnotation:`Text`,anchoredVWAP:`Anchored VWAP`,volumeProfileRange:`Volume Profile`};function se(e){return q[e]??e}var ce=/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;function le(e){return e.replace(/_/g,` `).replace(/([a-z0-9])([A-Z])/g,`$1 $2`).replace(/^./,e=>e.toUpperCase())}var ue=class{backdrop;modal;bodyEl;titleEl;callbacks;target=null;draft={};constructor(e,t){this.callbacks=t,this.backdrop=document.createElement(`div`),this.backdrop.className=`tcw-modal-backdrop`,this.backdrop.hidden=!0,this.backdrop.addEventListener(`click`,e=>{e.target===this.backdrop&&this.close()}),this.modal=document.createElement(`div`),this.modal.className=`tcw-modal tcw-modal-narrow`;let n=document.createElement(`div`);n.className=`tcw-modal-header`,this.titleEl=document.createElement(`h3`),this.titleEl.textContent=`Indicator`;let r=document.createElement(`button`);r.className=`tcw-modal-close`,r.setAttribute(`aria-label`,`Close`),r.innerHTML=_(`x`,16),r.addEventListener(`click`,()=>this.close()),n.appendChild(this.titleEl),n.appendChild(r),this.bodyEl=document.createElement(`div`),this.bodyEl.className=`tcw-modal-body`;let i=document.createElement(`div`);i.className=`tcw-modal-footer`;let a=document.createElement(`button`);a.className=`tcw-reset-link`,a.textContent=`Reset to defaults`,a.addEventListener(`click`,()=>this.resetDefaults());let o=document.createElement(`button`);o.className=`tcw-done-btn`,o.textContent=`Done`,o.addEventListener(`click`,()=>this.close()),i.appendChild(a),i.appendChild(o),this.modal.appendChild(n),this.modal.appendChild(this.bodyEl),this.modal.appendChild(i),this.backdrop.appendChild(this.modal),e.appendChild(this.backdrop)}open(e){this.target=e,this.titleEl.textContent=`${e.name} settings`,this.draft={},this.renderFields(),this.backdrop.hidden=!1}close(){this.backdrop.hidden=!0,this.target=null,this.callbacks.onClose()}isOpen(){return!this.backdrop.hidden}destroy(){this.backdrop.remove()}currentValue(e){if(e in this.draft)return this.draft[e];let t=this.target?.params[e],n=this.target?.defaults[e];return t??n}setValue(e,t){this.target&&(this.draft[e]=t,this.callbacks.onApply(this.target.instanceId,{...this.draft}))}resetDefaults(){if(!this.target)return;let e={};for(let[t,n]of Object.entries(this.target.defaults))e[t]=n;this.draft=e,this.callbacks.onApply(this.target.instanceId,{...e}),this.renderFields()}renderFields(){if(this.bodyEl.replaceChildren(),!this.target)return;let e=document.createElement(`div`);e.className=`tcw-settings-section`;let t=Object.keys(this.target.defaults);if(t.length===0){let t=document.createElement(`div`);t.className=`tcw-settings-label`,t.textContent=`This indicator has no adjustable parameters.`,e.appendChild(t)}for(let n of t)e.appendChild(this.fieldRow(n));this.bodyEl.appendChild(e)}fieldRow(e){let t=document.createElement(`div`);t.className=`tcw-settings-row`;let n=document.createElement(`span`);n.className=`tcw-settings-label`,n.textContent=le(e),t.appendChild(n);let r=this.currentValue(e),i=typeof(this.target?.defaults[e]??r);return i===`boolean`?t.appendChild(this.toggleControl(e,!!r)):i===`number`?t.appendChild(this.numberControl(e,Number(r))):typeof r==`string`&&ce.test(r)?t.appendChild(this.colorControl(e,r)):t.appendChild(this.textControl(e,String(r??``))),t}toggleControl(e,t){let n=document.createElement(`button`);return n.className=`tcw-toggle${t?` tcw-on`:``}`,n.type=`button`,n.addEventListener(`click`,()=>{let t=!n.classList.contains(`tcw-on`);n.classList.toggle(`tcw-on`,t),this.setValue(e,t)}),n}numberControl(e,t){let n=document.createElement(`input`);return n.type=`number`,n.className=`tcw-indi-input`,n.value=String(t),n.step=Number.isInteger(t)?`1`:`0.1`,n.addEventListener(`change`,()=>{let t=Number(n.value);Number.isFinite(t)&&this.setValue(e,t)}),n}colorControl(e,t){let n=document.createElement(`input`);return n.type=`color`,n.className=`tcw-indi-color`,n.value=t.length===4?de(t):t,n.addEventListener(`input`,()=>this.setValue(e,n.value)),n}textControl(e,t){let n=document.createElement(`input`);return n.type=`text`,n.className=`tcw-indi-input`,n.value=t,n.addEventListener(`change`,()=>this.setValue(e,n.value)),n}};function de(e){let t=e[1],n=e[2],r=e[3];return`#${t}${t}${n}${n}${r}${r}`}function fe(){try{return typeof localStorage<`u`?localStorage:null}catch{return null}}var pe=[`color`,`lineWidth`,`lineStyle`,`fillColor`,`fillOpacity`,`fontSize`];function J(e){if(!e||typeof e!=`object`)return{};let t={},n=e;for(let e of pe)n[e]!==void 0&&(t[e]=n[e]);return t}var me=class{templates=[];constructor(e=`tcw:draw-templates`,t=fe()){this.storageKey=e,this.storage=t,this.load()}list(){return this.templates.map(e=>({name:e.name,style:{...e.style}}))}get(e){let t=this.templates.find(t=>t.name===e);return t?{name:t.name,style:{...t.style}}:null}save(e,t){let n=e.trim();if(!n)return;let r=J(t);this.templates=this.templates.filter(e=>e.name!==n),this.templates.push({name:n,style:r}),this.persist()}remove(e){let t=this.templates.filter(t=>t.name!==e);t.length!==this.templates.length&&(this.templates=t,this.persist())}clear(){this.templates=[],this.persist()}load(){if(this.storage)try{let e=this.storage.getItem(this.storageKey);if(!e)return;let t=JSON.parse(e);if(!Array.isArray(t))return;this.templates=t.filter(e=>e&&typeof e.name==`string`).map(e=>({name:e.name,style:J(e.style)}))}catch{}}persist(){if(this.storage)try{this.storage.setItem(this.storageKey,JSON.stringify(this.templates))}catch{}}},he=[`#2962ff`,`#089981`,`#f23645`,`#ff9800`,`#ab47bc`,`#26c6da`,`#ffffff`,`#787b86`],ge=[1,2,3,4],_e=[`solid`,`dashed`,`dotted`],ve=class{el;templatesEl;nameInput;callbacks;store;open=!1;constructor(e,t,n){this.callbacks=t,this.store=n,this.el=document.createElement(`div`),this.el.className=`tcw-style-panel`,this.el.hidden=!0;let r=document.createElement(`div`);r.className=`tcw-style-header`;let i=document.createElement(`span`);i.textContent=`Drawing Style`;let a=document.createElement(`button`);a.type=`button`,a.className=`tcw-style-close`,a.setAttribute(`aria-label`,`Close`),a.innerHTML=_(`x`,14),a.addEventListener(`click`,()=>this.close()),r.appendChild(i),r.appendChild(a),this.el.appendChild(r),this.el.appendChild(this.colorRow()),this.el.appendChild(this.widthRow()),this.el.appendChild(this.lineStyleRow());let o=document.createElement(`div`);o.className=`tcw-style-subhead`,o.textContent=`Templates`,this.el.appendChild(o);let s=document.createElement(`div`);s.className=`tcw-style-save`,this.nameInput=document.createElement(`input`),this.nameInput.type=`text`,this.nameInput.placeholder=`Template name`,this.nameInput.className=`tcw-style-name`;let c=document.createElement(`button`);c.type=`button`,c.className=`tcw-style-savebtn`,c.innerHTML=`${_(`plus`,13)}<span>Save</span>`,c.addEventListener(`click`,()=>this.saveTemplate()),s.appendChild(this.nameInput),s.appendChild(c),this.el.appendChild(s),this.templatesEl=document.createElement(`div`),this.templatesEl.className=`tcw-style-templates`,this.el.appendChild(this.templatesEl),e.appendChild(this.el),this.renderTemplates()}isOpen(){return this.open}toggle(){this.open?this.close():this.openPanel()}openPanel(){this.open=!0,this.el.hidden=!1,this.syncActiveControls(),this.renderTemplates()}close(){this.open=!1,this.el.hidden=!0}destroy(){this.el.remove()}colorRow(){let e=document.createElement(`div`);e.className=`tcw-style-row tcw-style-colors`;for(let t of he){let n=document.createElement(`button`);n.type=`button`,n.className=`tcw-style-swatch`,n.style.background=t,n.dataset.color=t,n.setAttribute(`aria-label`,t),n.addEventListener(`click`,()=>this.applyStyle({color:t})),e.appendChild(n)}let t=document.createElement(`input`);return t.type=`color`,t.className=`tcw-style-picker`,t.addEventListener(`input`,()=>this.applyStyle({color:t.value})),e.appendChild(t),e}widthRow(){let e=document.createElement(`div`);e.className=`tcw-style-row tcw-style-widths`;for(let t of ge){let n=document.createElement(`button`);n.type=`button`,n.className=`tcw-style-width`,n.dataset.width=String(t);let r=document.createElement(`span`);r.style.height=`${t}px`,n.appendChild(r),n.addEventListener(`click`,()=>this.applyStyle({lineWidth:t})),e.appendChild(n)}return e}lineStyleRow(){let e=document.createElement(`div`);e.className=`tcw-style-row tcw-style-dashes`;for(let t of _e){let n=document.createElement(`button`);n.type=`button`,n.className=`tcw-style-dash`,n.dataset.linestyle=t,n.textContent=t===`solid`?`──`:t===`dashed`?`╌╌`:`┄┄`,n.title=t,n.addEventListener(`click`,()=>this.applyStyle({lineStyle:t})),e.appendChild(n)}return e}applyStyle(e){this.callbacks.onStyleChange(e),this.syncActiveControls()}syncActiveControls(){let e=this.callbacks.getStyle();this.el.querySelectorAll(`.tcw-style-swatch`).forEach(t=>{t.classList.toggle(`tcw-on`,t.dataset.color?.toLowerCase()===e.color?.toLowerCase())}),this.el.querySelectorAll(`.tcw-style-width`).forEach(t=>{t.classList.toggle(`tcw-on`,Number(t.dataset.width)===e.lineWidth)}),this.el.querySelectorAll(`.tcw-style-dash`).forEach(t=>{t.classList.toggle(`tcw-on`,t.dataset.linestyle===e.lineStyle)})}saveTemplate(){let e=this.nameInput.value.trim();e&&(this.store.save(e,this.callbacks.getStyle()),this.nameInput.value=``,this.renderTemplates())}renderTemplates(){this.templatesEl.replaceChildren();let e=this.store.list();if(e.length===0){let e=document.createElement(`div`);e.className=`tcw-style-empty`,e.textContent=`No saved templates`,this.templatesEl.appendChild(e);return}for(let t of e){let e=document.createElement(`div`);e.className=`tcw-style-template`;let n=document.createElement(`button`);n.type=`button`,n.className=`tcw-style-apply`;let r=document.createElement(`span`);r.className=`tcw-style-tdot`,r.style.background=t.style.color??`var(--tcw-text-muted)`;let i=document.createElement(`span`);i.textContent=t.name,n.appendChild(r),n.appendChild(i),n.addEventListener(`click`,()=>{this.callbacks.onStyleChange({...t.style}),this.syncActiveControls()});let a=document.createElement(`button`);a.type=`button`,a.className=`tcw-style-tdel`,a.setAttribute(`aria-label`,`Delete template`),a.innerHTML=_(`trash`,13),a.addEventListener(`click`,()=>{this.store.remove(t.name),this.renderTemplates()}),e.appendChild(n),e.appendChild(a),this.templatesEl.appendChild(e)}}};function ye(){try{return typeof localStorage<`u`?localStorage:null}catch{return null}}var be=class{favorites=[];constructor(e=`tcw:draw-favorites`,t=ye()){this.storageKey=e,this.storage=t,this.load()}list(){return[...this.favorites]}has(e){return this.favorites.includes(e)}add(e){!e||this.favorites.includes(e)||(this.favorites=[...this.favorites,e],this.persist())}remove(e){this.favorites.includes(e)&&(this.favorites=this.favorites.filter(t=>t!==e),this.persist())}toggle(e){return this.has(e)?(this.remove(e),!1):(this.add(e),!0)}seedDefaults(e){this.favorites.length>0||(this.favorites=[...new Set(e.filter(Boolean))],this.persist())}load(){if(this.storage)try{let e=this.storage.getItem(this.storageKey);if(!e)return;let t=JSON.parse(e);Array.isArray(t)&&(this.favorites=[...new Set(t.filter(e=>typeof e==`string`))])}catch{}}persist(){if(this.storage)try{this.storage.setItem(this.storageKey,JSON.stringify(this.favorites))}catch{}}},xe=class{el;labelEl;callbacks;visible=!1;constructor(e,t){this.callbacks=t,this.el=document.createElement(`div`),this.el.className=`tcw-bracket-bar`,this.el.hidden=!0,this.labelEl=document.createElement(`span`),this.labelEl.className=`tcw-bracket-label`,this.el.appendChild(this.labelEl);let n=document.createElement(`span`);n.className=`tcw-bracket-hint`,n.textContent=`drag lines to adjust`,this.el.appendChild(n);let r=document.createElement(`button`);r.type=`button`,r.className=`tcw-bracket-cancel`,r.innerHTML=`${_(`x`,14)}<span>Cancel</span>`,r.addEventListener(`click`,()=>this.callbacks.onCancel());let i=document.createElement(`button`);i.type=`button`,i.className=`tcw-bracket-confirm`,i.innerHTML=`${_(`check`,14)}<span>Place</span>`,i.addEventListener(`click`,()=>this.callbacks.onConfirm()),this.el.appendChild(r),this.el.appendChild(i),e.appendChild(this.el)}show(e){this.visible=!0,this.labelEl.textContent=e===`buy`?`Long bracket`:`Short bracket`,this.labelEl.dataset.side=e,this.el.hidden=!1}hide(){this.visible=!1,this.el.hidden=!0}isVisible(){return this.visible}destroy(){this.el.remove()}},Se=class{options;audioCtx=null;audioEl=null;permissionAsked=!1;constructor(e={}){if(this.options=e,typeof e.sound==`string`)try{this.audioEl=new Audio(e.sound),this.audioEl.preload=`auto`}catch{this.audioEl=null}e.desktop&&this.ensurePermission()}setOptions(e){this.options={...this.options,...e}}notify(e){this.options.sound&&this.playSound(),this.options.desktop&&this.showDesktop(e)}playSound(){if(this.audioEl){this.audioEl.currentTime=0,this.audioEl.play().catch(()=>{});return}this.beep()}beep(){try{let e=window.AudioContext??window.webkitAudioContext;if(!e)return;this.audioCtx||=new e;let t=this.audioCtx,n=t.currentTime,r=t.createGain();r.gain.setValueAtTime(1e-4,n),r.gain.exponentialRampToValueAtTime(.2,n+.01),r.gain.exponentialRampToValueAtTime(1e-4,n+.35),r.connect(t.destination);let i=t.createOscillator();i.type=`sine`,i.frequency.setValueAtTime(880,n),i.frequency.setValueAtTime(1320,n+.16),i.connect(r),i.start(n),i.stop(n+.36)}catch{}}ensurePermission(){this.permissionAsked||(this.permissionAsked=!0,!(typeof Notification>`u`)&&Notification.permission===`default`&&Notification.requestPermission().catch(()=>{}))}showDesktop(e){if(!(typeof Notification>`u`)){if(Notification.permission!==`granted`){this.ensurePermission();return}try{new Notification(this.options.title??`Price alert`,{body:e})}catch{}}}destroy(){try{this.audioCtx?.close()}catch{}this.audioCtx=null,this.audioEl=null}};function Ce(e,t=12){let n=[...e.asks].sort((e,t)=>e.price-t.price).slice(0,t),r=[...e.bids].sort((e,t)=>t.price-e.price).slice(0,t),i=n.length>0?n[0].price:null,a=r.length>0?r[0].price:null,o=i!==null&&a!==null?(i+a)/2:null,s=new Map,c=e=>{let t=s.get(e);return t||(t={price:e,bidVolume:0,askVolume:0},s.set(e,t)),t};for(let e of n)c(e.price).askVolume+=e.volume;for(let e of r)c(e.price).bidVolume+=e.volume;let l=[...s.values()].sort((e,t)=>t.price-e.price),u=0;for(let e of l)u=Math.max(u,e.bidVolume,e.askVolume);return{rows:l,maxVolume:u,mid:o}}var we=class{el;bodyEl;callbacks;open=!1;levels;constructor(e,t,n=12){this.callbacks=t,this.levels=n,this.el=document.createElement(`div`),this.el.className=`tcw-ladder`,this.el.hidden=!0;let r=document.createElement(`div`);r.className=`tcw-ladder-header`;let i=document.createElement(`span`);i.textContent=`Depth Ladder`;let a=document.createElement(`button`);a.type=`button`,a.className=`tcw-ladder-close`,a.setAttribute(`aria-label`,`Close`),a.innerHTML=_(`x`,14),a.addEventListener(`click`,()=>this.close()),r.appendChild(i),r.appendChild(a),this.el.appendChild(r);let o=document.createElement(`div`);o.className=`tcw-ladder-cols`,o.innerHTML=`<span>Bid</span><span>Price</span><span>Ask</span>`,this.el.appendChild(o),this.bodyEl=document.createElement(`div`),this.bodyEl.className=`tcw-ladder-body`,this.el.appendChild(this.bodyEl),e.appendChild(this.el)}isOpen(){return this.open}toggle(){this.open?this.close():this.openPanel()}openPanel(){this.open=!0,this.el.hidden=!1}close(){this.open=!1,this.el.hidden=!0}setData(e){if(!e){this.renderEmpty();return}this.render(Ce(e,this.levels))}destroy(){this.el.remove()}renderEmpty(){this.bodyEl.replaceChildren();let e=document.createElement(`div`);e.className=`tcw-ladder-empty`,e.textContent=`No order-book data`,this.bodyEl.appendChild(e)}render(e){if(this.bodyEl.replaceChildren(),e.rows.length===0){this.renderEmpty();return}let t=e.maxVolume>0?1/e.maxVolume:0;for(let n of e.rows){let e=n.askVolume>0,r=document.createElement(`div`);r.className=`tcw-ladder-row`;let i=document.createElement(`button`);i.type=`button`,i.className=`tcw-ladder-cell tcw-ladder-bid`,n.bidVolume>0?(i.textContent=Y(n.bidVolume),i.style.setProperty(`--w`,`${(n.bidVolume*t*100).toFixed(1)}%`),i.title=`Sell @ ${this.callbacks.formatPrice(n.price)}`,i.addEventListener(`click`,()=>this.callbacks.onTrade(`sell`,n.price))):i.disabled=!0;let a=document.createElement(`div`);a.className=`tcw-ladder-price ${e?`tcw-ask`:`tcw-bid`}`,a.textContent=this.callbacks.formatPrice(n.price);let o=document.createElement(`button`);o.type=`button`,o.className=`tcw-ladder-cell tcw-ladder-ask`,n.askVolume>0?(o.textContent=Y(n.askVolume),o.style.setProperty(`--w`,`${(n.askVolume*t*100).toFixed(1)}%`),o.title=`Buy @ ${this.callbacks.formatPrice(n.price)}`,o.addEventListener(`click`,()=>this.callbacks.onTrade(`buy`,n.price))):o.disabled=!0,r.appendChild(i),r.appendChild(a),r.appendChild(o),this.bodyEl.appendChild(r)}}};function Y(e){return e>=1e3?(e/1e3).toFixed(1)+`k`:e>=1?e.toFixed(2).replace(/\.00$/,``):e.toPrecision(2)}var Te=class{el;bodyEl;callbacks;open=!1;constructor(e,t){this.callbacks=t,this.el=document.createElement(`div`),this.el.className=`tcw-datawin`,this.el.hidden=!0;let n=document.createElement(`div`);n.className=`tcw-datawin-header`;let r=document.createElement(`span`);r.textContent=`Data Window`;let i=document.createElement(`button`);i.type=`button`,i.className=`tcw-datawin-close`,i.setAttribute(`aria-label`,`Close`),i.innerHTML=_(`x`,14),i.addEventListener(`click`,()=>this.close()),n.appendChild(r),n.appendChild(i),this.el.appendChild(n),this.bodyEl=document.createElement(`div`),this.bodyEl.className=`tcw-datawin-body`,this.el.appendChild(this.bodyEl),e.appendChild(this.el)}isOpen(){return this.open}toggle(){this.open?this.close():this.openPanel()}openPanel(){this.open=!0,this.el.hidden=!1}close(){this.open=!1,this.el.hidden=!0}destroy(){this.el.remove()}render(e){if(!this.open)return;if(this.bodyEl.replaceChildren(),!e.ohlc){let e=document.createElement(`div`);e.className=`tcw-datawin-empty`,e.textContent=`Hover the chart`,this.bodyEl.appendChild(e);return}let t=this.callbacks.formatPrice,n=e.ohlc;this.bodyEl.appendChild(this.row(`Open`,t(n.open))),this.bodyEl.appendChild(this.row(`High`,t(n.high))),this.bodyEl.appendChild(this.row(`Low`,t(n.low))),this.bodyEl.appendChild(this.row(`Close`,t(n.close)));let r=e.change>0?`up`:e.change<0?`down`:``,i=e.change>0?`+`:``;this.bodyEl.appendChild(this.row(`Change`,`${i}${t(e.change)} (${i}${e.changePct.toFixed(2)}%)`,r)),this.bodyEl.appendChild(this.row(`Volume`,De(n.volume)));for(let t of e.indicators){let e=document.createElement(`div`);e.className=`tcw-datawin-sub`,e.textContent=t.name,this.bodyEl.appendChild(e);for(let e of t.values)this.bodyEl.appendChild(this.row(e.key,Ee(e.value)))}}row(e,t,n=``){let r=document.createElement(`div`);r.className=`tcw-datawin-row`;let i=document.createElement(`span`);i.className=`tcw-datawin-label`,i.textContent=e;let a=document.createElement(`span`);return a.className=`tcw-datawin-value${n?` tcw-${n}`:``}`,a.textContent=t,r.appendChild(i),r.appendChild(a),r}};function Ee(e){if(!Number.isFinite(e))return`—`;let t=Math.abs(e);return t>=1e3?e.toFixed(2):t>=1?e.toFixed(4):e.toPrecision(4)}function De(e){return e>=1e9?(e/1e9).toFixed(2)+`B`:e>=1e6?(e/1e6).toFixed(2)+`M`:e>=1e3?(e/1e3).toFixed(2)+`K`:e.toFixed(0)}var X=globalThis.Buffer;function Oe(e){if(X)return X.from(e,`utf8`).toString(`base64`);let t=new TextEncoder().encode(e),n=``;for(let e of t)n+=String.fromCharCode(e);return btoa(n)}function ke(e){if(X)return X.from(e,`base64`).toString(`utf8`);let t=atob(e),n=new Uint8Array(t.length);for(let e=0;e<t.length;e++)n[e]=t.charCodeAt(e);return new TextDecoder().decode(n)}function Z(e){return e.replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``)}function Ae(e){let t=e.replace(/-/g,`+`).replace(/_/g,`/`);return t+(t.length%4==0?``:`=`.repeat(4-t.length%4))}function je(e){return Z(Oe(JSON.stringify(e)))}function Me(e){if(!e)return null;try{let t=ke(Ae(e)),n=JSON.parse(t);return!n||n.v!==1||typeof n.symbol!=`string`?null:{v:1,symbol:n.symbol,timeframe:n.timeframe,chartType:n.chartType,scaleMode:n.scaleMode??`regular`,indicators:Array.isArray(n.indicators)?n.indicators:[],drawings:Array.isArray(n.drawings)?n.drawings:[]}}catch{return null}}var Q=`tcw`;function Ne(e){let t=e.startsWith(`#`)?e.slice(1):e;for(let e of t.split(`&`)){let t=e.indexOf(`=`);if(t>0&&e.slice(0,t)===Q)return decodeURIComponent(e.slice(t+1))}return null}function Pe(e,t){let[n]=e.split(`#`);return`${n}#${Q}=${t}`}var $=[`#f7931a`,`#627eea`,`#26a17b`,`#e84142`,`#8247e5`,`#f3ba2f`],Fe=class{chart;state;toolbar=null;sidebar=null;settings=null;statusBar=null;commandPalette=null;symbolSearch=null;hotkeySheet=null;replayBar=null;dragDrop=null;alertsPanel=null;objectTree=null;indicatorSettings=null;drawingStyle=null;bracketBar=null;alertNotifier=null;depthLadder=null;dataWindow=null;lastHoverIndex=null;favoritesStore=new be;watchlist=null;watchlistSparkBuffer=new Map;sessionRefPrice=null;watchlistInterval=null;replayOriginalData=null;replayPollInterval=null;replaySpeed=5;layoutKeyPrefix=null;layoutDebounceMs=1500;activeLayoutKey=null;root;chartContainer;destroyed=!1;options;symbols;settingsState;adapter=null;boundGlobalKeydown=null;baseSeries=null;baseTimeframeMs=0;compares=[];constructor(t,n={}){if(this.options=n,this.symbols=n.symbols??l,this.settingsState={...u},n.persistLayouts){let e=n.persistLayouts===!0?{}:n.persistLayouts;this.layoutKeyPrefix=e.keyPrefix??`tcw:layout:`,this.layoutDebounceMs=e.debounceMs??1500}let r=this.resolveIsDark(n.theme),d=this.resolveTheme(n.theme);this.state={symbol:n.symbol??this.symbols[0]??`BTCUSDT`,timeframe:n.timeframe??`5m`,chartType:n.chartOptions?.chartType??`candlestick`,isDark:r,activeIndicators:new Map,activeTool:null,magnetEnabled:!0,connectionState:`connecting`,connectionMessage:`Connecting...`},m(),this.root=document.createElement(`div`),this.root.className=`tcw-root`,this.root.dataset.tcwTheme=r?`dark`:`light`,t.appendChild(this.root),n.toolbar!==!1&&(this.toolbar=new y(this.root,{symbols:this.symbols,timeframes:n.timeframes?i.filter(e=>n.timeframes.includes(e.value)):i,chartTypes:n.chartTypes?a.filter(e=>n.chartTypes.includes(e.value)):a,indicators:s,popularIndicatorIds:c},{onSymbolClick:()=>this.handleSymbolClick(),onTimeframe:e=>this.handleTimeframe(e),onChartType:e=>this.handleChartType(e),onAddIndicator:e=>this.handleAddIndicator(e),onRemoveIndicator:e=>this.handleRemoveIndicator(e),onScreenshot:()=>this.chart.screenshot(),onSettings:()=>this.openSettings(),onToggleTheme:()=>this.handleToggleTheme(),onToggleReplay:()=>this.toggleReplay(),onToggleAlerts:n.alerts===!1?void 0:()=>this.toggleAlerts(),onToggleObjects:n.objectTree===!1?void 0:()=>this.toggleObjects(),onBracket:n.trading===!1?void 0:e=>this.startBracket(e),onToggleLadder:n.trading!==!1&&n.depthLadder?()=>this.depthLadder?.toggle():void 0}));let f=document.createElement(`div`);if(f.className=`tcw-body`,n.drawingTools!==!1&&(n.drawingFavorites&&this.favoritesStore.seedDefaults(n.drawingFavorites),this.sidebar=new ie(f,{drawingToolGroups:o,favorites:this.favoritesStore.list()},{onDrawingTool:e=>this.handleDrawingTool(e),onCancelDrawing:()=>this.handleCancelDrawing(),onToggleMagnet:()=>this.handleToggleMagnet(),onToggleFavorite:e=>this.handleToggleFavorite(e),onUndo:()=>this.chart.undo(),onRedo:()=>this.chart.redo(),onClearDrawings:()=>{this.chart.clearDrawings(),this.state={...this.state,activeTool:null},this.updateUI()},onToggleStyle:()=>this.drawingStyle?.toggle()})),this.chartContainer=document.createElement(`div`),this.chartContainer.className=`tcw-chart-container`,f.appendChild(this.chartContainer),n.watchlist&&(this.watchlist=new L(f,this.symbols,{onSelect:e=>{this.setSymbol(e)}}),this.watchlist.setActive(this.state.symbol)),this.root.appendChild(f),this.chart=new e.r(this.chartContainer,{chartType:this.state.chartType,theme:d,autoScale:!0,crosshair:{mode:`magnet`},features:{drawings:!0,drawingMagnet:!0,drawingUndoRedo:!0,indicators:!0,trading:n.trading!==!1,tradingContextMenu:n.trading!==!1,volume:!0,legend:!0,crosshair:!0,keyboard:!0,screenshot:!0,alerts:!0,barCountdown:!0,logScale:!0,watermark:!0},...n.chartOptions}),n.dragDropImport!==!1&&(this.dragDrop=new e.t(this.chartContainer,{onData:(e,t,n)=>{this.setData(e),this.toast(`Loaded ${t.data.length} bars from ${n.name}`+(t.skipped>0?` (${t.skipped} skipped)`:``))},onError:(e,t)=>{this.toast(`${t.name}: ${e.message}`,`error`)}}),this.dragDrop.attach()),n.statusBar!==!1&&(this.statusBar=new b(this.root)),n.settings!==!1&&(this.settings=new oe({onChange:e=>this.applySettings(e),onReset:()=>this.resetSettings(),onClose:()=>{}})),this.symbolSearch=new S({onPick:e=>{this.setSymbol(e)},onClose:()=>{}}),this.hotkeySheet=new k({onClose:()=>{}}),this.chart.on(`barClick`,e=>{if(!this.replayBar?.isMounted())return;let t=e.payload.barIndex;typeof t==`number`&&(this.chart.getReplayState()===`playing`&&this.chart.replayPause(),this.chart.replaySeek(t),this.replayBar.setState(`paused`))}),this.dataWindow=new Te(this.root,{formatPrice:e=>this.formatAlertPrice(e)}),this.chart.on(`crosshairMove`,e=>{let t=e.payload;this.lastHoverIndex=typeof t.barIndex==`number`?t.barIndex:null,this.dataWindow?.isOpen()&&this.dataWindow.render(this.buildDataWindowModel())}),n.drawingTools!==!1&&(this.drawingStyle=new ve(this.root,{onStyleChange:e=>{this.chart.setDrawingStyle(e),this.chart.setSelectedDrawingStyle(e)},getStyle:()=>this.chart.getDrawingStyle()},new me)),n.trading!==!1&&(this.bracketBar=new xe(this.root,{onConfirm:()=>this.chart.confirmBracket(),onCancel:()=>{this.chart.cancelBracket(),this.bracketBar?.hide()}}),this.chart.on(`bracketPlace`,e=>{let t=e.payload;this.bracketBar?.hide(),this.toast(`${t.side===`buy`?`Long`:`Short`} bracket placed · ${t.riskReward.toFixed(2)}R`)}),n.depthLadder&&(this.depthLadder=new we(this.root,{onTrade:(e,t)=>{this.chart.placeOrderIntent({side:e,type:`limit`,price:t}),this.toast(`${e===`buy`?`Buy`:`Sell`} limit @ ${this.formatAlertPrice(t)}`)},formatPrice:e=>this.formatAlertPrice(e)})),this.chart.on(`dataUpdate`,e=>{let t=e.payload;t&&t.bracket===`cancelled`&&this.bracketBar?.hide()})),n.alerts!==!1&&(this.alertsPanel=new G(this.root,{onAdd:(e,t,n,r,i)=>{this.chart.addAlert(e,t,n,r,i)},onRemove:e=>this.chart.removeAlert(e),onClear:()=>this.chart.clearAlerts(),getChannelValue:e=>this.getAlertChannelValue(e),formatPrice:e=>this.formatAlertPrice(e)}),this.chart.on(`alertAdd`,()=>this.refreshAlerts()),this.chart.on(`alertRemove`,()=>this.refreshAlerts()),this.chart.on(`alertUpdate`,()=>this.refreshAlerts()),n.alertNotifications&&(this.alertNotifier=new Se(n.alertNotifications)),this.chart.on(`alertTriggered`,e=>{let t=e.payload,n=`Price ${this.formatAlertPrice(t.price)}${t.message?` — ${t.message}`:``}`;this.toast(`🔔 Alert: ${n}`,`info`),this.alertNotifier?.notify(n),this.refreshAlerts()})),n.objectTree!==!1){this.indicatorSettings=new ue(this.root,{onApply:(e,t)=>this.chart.updateIndicator(e,t),onClose:()=>{}}),this.objectTree=new K(this.root,{onRemoveIndicator:e=>this.handleRemoveIndicator(e),onConfigureIndicator:e=>this.openIndicatorSettings(e),onToggleIndicatorVisible:(e,t)=>{this.chart.setIndicatorVisible(e,t),this.refreshObjects()},onRemoveDrawing:e=>{this.chart.removeDrawing(e),this.refreshObjects()},onToggleDrawingVisible:(e,t)=>{this.chart.setDrawingVisible(e,t),this.refreshObjects()},onToggleDrawingLocked:(e,t)=>{this.chart.setDrawingLocked(e,t),this.refreshObjects()},onAddCompare:()=>this.handleAddCompare(),onRemoveCompare:e=>this.handleRemoveCompare(e)});let e=()=>{this.objectTree?.isOpen()&&this.refreshObjects()};this.chart.on(`drawingCreate`,e),this.chart.on(`drawingRemove`,e),this.chart.on(`indicatorAdd`,e),this.chart.on(`indicatorRemove`,e)}if(this.commandPalette=new x({onIndicator:e=>this.handleAddIndicator(e),onChartType:e=>this.handleChartType(e),onDrawingTool:e=>this.handleDrawingTool(e),onTimeframe:e=>this.handleTimeframe(e),onAction:e=>this.handleAction(e),onClose:()=>{}}),this.boundGlobalKeydown=e=>{if((e.ctrlKey||e.metaKey)&&e.key===`k`)e.preventDefault(),this.toggleCommandPalette();else if((e.ctrlKey||e.metaKey)&&(e.key===`p`||e.key===`P`))e.preventDefault(),this.symbolSearch?.open(this.symbols,this.state.symbol);else if(e.key===`?`&&!e.ctrlKey&&!e.metaKey&&!e.altKey){let t=document.activeElement;if(t&&(t.tagName===`INPUT`||t.tagName===`TEXTAREA`||t.isContentEditable))return;e.preventDefault(),this.hotkeySheet?.open()}},document.addEventListener(`keydown`,this.boundGlobalKeydown),n.adapter&&(this.adapter=n.adapter,this.connectStream()),this.watchlist&&(this.watchlistInterval=setInterval(()=>this.tickWatchlist(),1e3)),this.updateUI(),n.onReady?.(this.chart),n.shareUrl&&typeof location<`u`){let e=Ne(location.hash);e&&this.importState(e)}}setSymbols(e){this.symbols=e,this.watchlist?.setSymbols(e)}async setSymbol(e){this.flushActiveLayout(),this.state={...this.state,symbol:e},this.sessionRefPrice=null,this.options.onSymbolChange?.(e),this.updateUI(),this.watchlist?.setActive(e),this.adapter&&await this.connectStream()}setWatchlistEntry(e,t){this.watchlist?.setEntry(e,t)}tickWatchlist(){if(!this.watchlist)return;let e=this.chart.getData();if(e.length===0)return;let t=e[e.length-1];this.sessionRefPrice===null&&(this.sessionRefPrice=e[0].open);let n=this.watchlistSparkBuffer.get(this.state.symbol)??[];n.push(t.close),n.length>40&&n.shift(),this.watchlistSparkBuffer.set(this.state.symbol,n),this.watchlist.setEntry(this.state.symbol,{lastPrice:t.close,refPrice:this.sessionRefPrice,sparkline:n.slice()})}async setTimeframe(e){if(this.state={...this.state,timeframe:e},this.options.onTimeframeChange?.(e),this.updateUI(),this.adapter){await this.connectStream();return}this.options.resampleTimeframes!==!1&&this.applyTimeframeData()}setTheme(e){let t=this.resolveIsDark(e),n=this.resolveTheme(e);this.state={...this.state,isDark:t},this.root.dataset.tcwTheme=t?`dark`:`light`,this.chart.setTheme(n),this.updateUI()}getChart(){return this.chart}destroy(){this.destroyed||(this.destroyed=!0,this.boundGlobalKeydown&&document.removeEventListener(`keydown`,this.boundGlobalKeydown),this.flushActiveLayout(),this.commandPalette?.destroy(),this.symbolSearch?.destroy(),this.hotkeySheet?.destroy(),this.replayPollInterval&&clearInterval(this.replayPollInterval),this.replayBar?.destroy(),this.dragDrop?.detach(),this.alertsPanel?.destroy(),this.objectTree?.destroy(),this.indicatorSettings?.destroy(),this.drawingStyle?.destroy(),this.bracketBar?.destroy(),this.alertNotifier?.destroy(),this.depthLadder?.destroy(),this.dataWindow?.destroy(),this.watchlistInterval&&clearInterval(this.watchlistInterval),this.watchlist?.destroy(),this.toolbar?.destroy(),this.sidebar?.destroy(),this.settings?.destroy(),this.statusBar?.destroy(),this.chart.destroy(),this.root.remove(),h())}handleSymbolClick(){this.symbolSearch?.open(this.symbols,this.state.symbol)}handleTimeframe(e){if(this.state={...this.state,timeframe:e},this.options.onTimeframeChange?.(e),this.updateUI(),this.adapter){this.connectStream();return}if(this.options.resampleTimeframes!==!1){if(!this.baseSeries){let e=this.chart.getData();e.length>0&&(this.baseSeries=e,this.baseTimeframeMs=r(e))}this.applyTimeframeData()}}setData(e){this.baseSeries=e,this.baseTimeframeMs=r(e),this.applyTimeframeData()}applyTimeframeData(){if(!this.baseSeries)return;let e=(0,t.timeframeToMs)(this.state.timeframe);if(this.baseTimeframeMs>0&&e>this.baseTimeframeMs){let e=this.options.weekStartsOn??1;this.chart.setData(n(this.baseSeries,this.state.timeframe,{weekStartsOn:e}))}else this.chart.setData(this.baseSeries)}toggleAlerts(){this.alertsPanel&&(this.alertsPanel.toggle(),this.alertsPanel.isOpen()&&this.refreshAlerts())}handleToggleFavorite(e){let t=this.favoritesStore.toggle(e);this.sidebar?.setFavorites(this.favoritesStore.list()),this.toast(t?`Pinned to favorites`:`Unpinned`)}exportState(){let e=this.chart.getActiveIndicators().map(e=>({id:e.id,params:e.params}));return je({v:1,symbol:this.state.symbol,timeframe:this.state.timeframe,chartType:this.state.chartType,scaleMode:this.chart.getScaleMode(),indicators:e,drawings:this.chart.getDrawings()})}async importState(e){let t=Me(e);if(!t)return!1;t.symbol&&t.symbol!==this.state.symbol&&await this.setSymbol(t.symbol),t.timeframe&&t.timeframe!==this.state.timeframe&&await this.setTimeframe(t.timeframe),t.chartType&&this.handleChartType(t.chartType),this.chart.setScaleMode(t.scaleMode);for(let[,e]of this.state.activeIndicators)this.chart.removeIndicator(e);let n=new Map;for(let e of t.indicators){let t=this.chart.addIndicator(e.id,e.params);t&&n.set(e.id,t)}return this.state={...this.state,activeIndicators:n},this.chart.setDrawings(t.drawings),this.updateUI(),!0}async copyChartImage(){let e=await this.chart.copyScreenshot();this.toast(e?`Chart image copied`:`Copy failed — image clipboard unavailable`,e?`info`:`error`)}async copyShareLink(){let e=Pe(typeof location<`u`?location.href:``,this.exportState());try{await navigator.clipboard.writeText(e),this.toast(`Share link copied`)}catch{this.toast(`Copy failed — clipboard unavailable`,`error`)}}setDepth(e){this.chart.setDepthData(e),this.depthLadder?.setData(e),e&&this.chart.pushDepthSnapshot(e)}startBracket(e){this.chart.startBracket(e)&&this.bracketBar?.show(e)}buildDataWindowModel(){let e=this.chart.getData(),t=this.lastHoverIndex;if(t===null||t<0||t>=e.length)return{ohlc:null,change:0,changePct:0,indicators:[]};let n=e[t],r=t>0?e[t-1].close:n.open,i=n.close-r,a=r===0?0:i/r*100,o=this.chart.getActiveIndicators().map(e=>{let n=this.chart.getIndicatorOutput(e.instanceId)?.series?.[t]??null,r=n?Object.entries(n).filter(([,e])=>typeof e==`number`&&Number.isFinite(e)).map(([e,t])=>({key:e,value:t})):[];return{name:e.descriptor.name,values:r}}).filter(e=>e.values.length>0);return{ohlc:{open:n.open,high:n.high,low:n.low,close:n.close,volume:n.volume},change:i,changePct:a,indicators:o}}toggleDataWindow(){this.dataWindow&&(this.dataWindow.toggle(),this.dataWindow.isOpen()&&this.dataWindow.render(this.buildDataWindowModel()))}toggleObjects(){this.objectTree&&(this.objectTree.toggle(),this.objectTree.isOpen()&&this.refreshObjects())}openIndicatorSettings(e){if(!this.indicatorSettings)return;let t=this.chart.getActiveIndicators().find(t=>t.instanceId===e);t&&this.indicatorSettings.open({instanceId:e,name:t.descriptor.name,defaults:t.descriptor.defaultConfig,params:t.params})}refreshObjects(){if(!this.objectTree)return;let e=this.chart.getActiveIndicators().map(e=>({instanceId:e.instanceId,name:e.descriptor.name,visible:e.visible})),t=this.chart.getDrawings().map(e=>({id:e.id,label:se(e.type),visible:e.visible,locked:e.locked})),n=this.compares.map(e=>({id:e.id,label:e.symbol,color:e.color}));this.objectTree.setObjects(e,t,n)}async handleAddCompare(){if(!this.adapter){this.toast(`Comparison needs a live data adapter`,`error`);return}let e=new Set([this.state.symbol,...this.compares.map(e=>e.symbol)]),t=this.symbols.filter(t=>!e.has(t));this.symbolSearch?.open(t.length?t:this.symbols,this.state.symbol,e=>{this.addCompareSymbol(e)})}async addCompareSymbol(e){if(!this.adapter||this.compares.some(t=>t.symbol===e))return;let t=$[this.compares.length%$.length],n=`cmp_${e}`;try{let r=await this.adapter.fetchHistory(e,this.state.timeframe,this.options.historyLimit??500);this.compares.length===0&&this.chart.setCompareMode(`percent`),this.chart.addCompareSymbol(n,e,r,t),this.compares=[...this.compares,{id:n,symbol:e,color:t}],this.refreshObjects(),this.toast(`Comparing ${e}`)}catch(t){this.toast(`${e}: ${t instanceof Error?t.message:`failed to load`}`,`error`)}}handleRemoveCompare(e){this.chart.removeCompareSymbol(e),this.compares=this.compares.filter(t=>t.id!==e),this.refreshObjects()}async refetchCompares(){if(!this.adapter||this.compares.length===0)return;let e=this.compares.filter(e=>e.symbol===this.state.symbol);for(let t of e)this.handleRemoveCompare(t.id);for(let e of this.compares)try{let t=await this.adapter.fetchHistory(e.symbol,this.state.timeframe,this.options.historyLimit??500);this.chart.updateCompareData(e.id,t)}catch{}}refreshAlerts(){this.alertsPanel&&(this.alertsPanel.setSources(this.buildAlertSources()),this.alertsPanel.setAlerts(this.chart.getAlerts().map(e=>({id:e.id,price:e.price,condition:e.condition,message:e.message,triggered:e.triggered,channel:e.channel,label:e.label}))))}buildAlertSources(){let e=[{channel:`price`,label:`Price`}];for(let t of this.chart.getActiveIndicators()){let n=this.chart.getIndicatorOutput(t.instanceId)?.series,r=n&&n.length>0?n[n.length-1]:null,i=r?Object.keys(r).filter(e=>typeof r[e]==`number`):[];for(let n of i){let r=i.length>1?`${t.descriptor.name} ${n}`:t.descriptor.name;e.push({channel:`${t.instanceId}:${n}`,label:r})}}return e}getAlertChannelValue(e){let t=this.chart.getData();if(e===`price`)return t.length>0?t[t.length-1].close:null;let n=e.indexOf(`:`);if(n<0||t.length===0)return null;let r=e.slice(0,n),i=e.slice(n+1),a=this.chart.getIndicatorOutput(r)?.series?.[t.length-1]?.[i];return typeof a==`number`&&Number.isFinite(a)?a:null}formatAlertPrice(e){let t=Math.abs(e),n=t>=1e3?2:t>=1?4:6,r=this.settingsState.numberLocale||void 0;return e.toLocaleString(r,{minimumFractionDigits:2,maximumFractionDigits:n})}handleChartType(e){this.state={...this.state,chartType:e},this.chart.setChartType(e),this.updateUI()}handleAddIndicator(e){if(this.state.activeIndicators.has(e)){let t=this.state.activeIndicators.get(e);this.chart.removeIndicator(t);let n=new Map(this.state.activeIndicators);n.delete(e),this.state={...this.state,activeIndicators:n}}else{let t=this.chart.addIndicator(e);if(t){let n=new Map(this.state.activeIndicators);n.set(e,t),this.state={...this.state,activeIndicators:n}}}this.updateUI()}handleRemoveIndicator(e){this.chart.removeIndicator(e);let t=new Map(this.state.activeIndicators);for(let[n,r]of t.entries())if(r===e){t.delete(n);break}this.state={...this.state,activeIndicators:t},this.updateUI()}toggleCommandPalette(){if(this.commandPalette?.isOpen()){this.commandPalette.close();return}this.commandPalette?.open(this.buildCommandItems())}buildCommandItems(){let e=[];for(let t of s)e.push({id:t.id,label:t.name,category:`indicator`,active:this.state.activeIndicators.has(t.id)});for(let t of a)e.push({id:t.value,label:t.label,category:`chartType`,active:this.state.chartType===t.value});for(let t of o)for(let n of t.tools)e.push({id:n.value,label:n.label,category:`drawing`,active:this.state.activeTool===n.value});for(let t of i)e.push({id:t.value,label:t.label,category:`timeframe`,active:this.state.timeframe===t.value});return e.push({id:`screenshot`,label:`Screenshot`,category:`action`,shortcut:``},{id:`copyImage`,label:`Copy Chart Image`,category:`action`},{id:`toggleTheme`,label:`Toggle Theme`,category:`action`},{id:`settings`,label:`Settings`,category:`action`},{id:`shareView`,label:`Share View (copy link)`,category:`action`},{id:`autoFib`,label:`Auto Fibonacci (visible swing)`,category:`action`},{id:`dataWindow`,label:`Toggle Data Window`,category:`action`},{id:`clearDrawings`,label:`Clear All Drawings`,category:`action`}),e}handleAction(e){switch(e){case`screenshot`:this.chart.screenshot();break;case`toggleTheme`:this.handleToggleTheme();break;case`settings`:this.openSettings();break;case`copyImage`:this.copyChartImage();break;case`shareView`:this.copyShareLink();break;case`autoFib`:{let e=this.chart.autoFib();this.toast(e?`Auto Fibonacci added`:`No clear swing in view`);break}case`dataWindow`:this.toggleDataWindow();break;case`clearDrawings`:this.chart.clearDrawings(),this.state={...this.state,activeTool:null},this.updateUI();break}}handleDrawingTool(e){this.state={...this.state,activeTool:e},this.chart.setDrawingTool(e),this.updateUI()}handleCancelDrawing(){this.state={...this.state,activeTool:null},this.chart.setDrawingTool(null),this.updateUI()}handleToggleMagnet(){let e=!this.state.magnetEnabled;this.state={...this.state,magnetEnabled:e},this.chart.setDrawingMagnet(e),this.updateUI()}handleToggleTheme(){let e=!this.state.isDark;this.state={...this.state,isDark:e},this.root.dataset.tcwTheme=e?`dark`:`light`,this.chart.setTheme(e?t.DARK_THEME:t.LIGHT_THEME),this.chart.setWatermark(this.state.symbol.replace(`USDT`,` / USDT`),{fontSize:48,color:e?`rgba(255,255,255,0.03)`:`rgba(0,0,0,0.03)`}),this.updateUI()}openSettings(){this.settings?.open(this.settingsState)}toast(e,t=`info`){let n=document.createElement(`div`);n.className=`tcw-toast ${t===`error`?`tcw-toast-error`:``}`,n.textContent=e,this.root.appendChild(n),requestAnimationFrame(()=>n.classList.add(`tcw-toast-in`)),setTimeout(()=>{n.classList.remove(`tcw-toast-in`),n.addEventListener(`transitionend`,()=>n.remove(),{once:!0}),setTimeout(()=>n.remove(),400)},3500)}clearSavedLayout(e){if(!this.layoutKeyPrefix)return;let t=e??this.state.symbol;try{localStorage.removeItem(this.layoutKeyPrefix+t)}catch{}}applySymbolLayout(e){if(!this.layoutKeyPrefix)return;let t=this.layoutKeyPrefix+e;this.activeLayoutKey=t;try{this.chart.loadStateFromStorage(t)&&this.rebuildActiveIndicatorsMapFromChart()}catch{}this.chart.setAutoSave(t,this.layoutDebounceMs)}flushActiveLayout(){if(this.activeLayoutKey){try{this.chart.saveState(this.activeLayoutKey)}catch{}this.chart.disableAutoSave(),this.activeLayoutKey=null}}rebuildActiveIndicatorsMapFromChart(){let e=new Map;for(let t of this.chart.getActiveIndicators())e.set(t.id,t.instanceId);this.state={...this.state,activeIndicators:e},this.updateUI()}toggleReplay(){this.replayBar?.isMounted()?this.exitReplay():this.enterReplay()}enterReplay(){let e=this.chart.getData();e.length<2||(this.replayOriginalData=e.slice(),this.replayBar=new j({onPlay:()=>{this.chart.getReplayState()===`paused`?this.chart.replayResume():this.chart.replayStart({speed:this.replaySpeed,interval:200}),this.replayBar?.setState(`playing`)},onPause:()=>{this.chart.replayPause(),this.replayBar?.setState(`paused`)},onStop:()=>{this.chart.replayStop(),this.replayBar?.setState(`paused`)},onStepBack:()=>{let e=this.chart.getReplayProgress();this.chart.getReplayState()===`playing`&&this.chart.replayPause(),this.chart.replaySeek(Math.max(0,e.current-1)),this.replayBar?.setState(`paused`)},onStepForward:()=>{let e=this.chart.getReplayProgress();this.chart.getReplayState()===`playing`&&this.chart.replayPause(),this.chart.replaySeek(Math.min(e.total-1,e.current+1)),this.replayBar?.setState(`paused`)},onSeek:e=>{this.chart.getReplayState()===`playing`&&this.chart.replayPause(),this.chart.replaySeek(e),this.replayBar?.setState(`paused`)},onSpeedChange:e=>{this.replaySpeed=e,this.chart.setReplaySpeed(e)},onClose:()=>this.exitReplay()}),this.replayBar.mount(this.chartContainer,{total:e.length,speed:this.replaySpeed}),this.chart.replayStart({speed:this.replaySpeed,interval:200,startIndex:1}),this.chart.replayPause(),this.replayBar.setState(`paused`),this.replayPollInterval=setInterval(()=>{if(!this.replayBar?.isMounted())return;let e=this.chart.getReplayProgress();this.replayBar.setProgress(e.current,e.total);let t=this.chart.getReplayState();t===`stopped`?this.replayBar.setState(`paused`):this.replayBar.setState(t)},150))}exitReplay(){this.replayPollInterval&&=(clearInterval(this.replayPollInterval),null),this.chart.replayStop(),this.replayBar?.unmount(),this.replayBar=null,this.replayOriginalData&&=(this.chart.setData(this.replayOriginalData),null)}applySettings(e){this.settingsState={...this.settingsState,...e},e.gridVisible!==void 0&&this.chart.setGridVisible(e.gridVisible),e.volumeVisible!==void 0&&this.chart.setVolumeVisible(e.volumeVisible),e.volumeProfileVisible!==void 0&&this.chart.setVolumeProfileVisible(e.volumeProfileVisible),e.marketProfileVisible!==void 0&&this.chart.setMarketProfileVisible(e.marketProfileVisible),e.marketProfileSplit!==void 0&&this.chart.setMarketProfileConfig({splitBySession:e.marketProfileSplit}),e.marketProfileLetters!==void 0&&this.chart.setMarketProfileConfig({letters:e.marketProfileLetters}),e.marketProfileBuckets!==void 0&&this.chart.setMarketProfileConfig({buckets:e.marketProfileBuckets}),e.marketProfileOpacity!==void 0&&this.chart.setMarketProfileConfig({opacity:e.marketProfileOpacity}),e.depthHeatmapVisible!==void 0&&this.chart.setDepthHeatmapVisible(e.depthHeatmapVisible),e.depthHeatmapOpacity!==void 0&&this.chart.setDepthHeatmapConfig({opacity:e.depthHeatmapOpacity}),e.sessionShadingVisible!==void 0&&this.chart.setSessionShadingVisible(e.sessionShadingVisible),e.pivotMarkersVisible!==void 0&&this.chart.setPivotMarkersVisible(e.pivotMarkersVisible),e.pivotStrength!==void 0&&this.chart.setPivotMarkersConfig({left:e.pivotStrength,right:e.pivotStrength}),e.pivotStructureLabels!==void 0&&this.chart.setPivotMarkersConfig({structureLabels:e.pivotStructureLabels}),e.periodLevelsVisible!==void 0&&this.chart.setPeriodLevelsVisible(e.periodLevelsVisible),e.periodLevelsPeriod!==void 0&&this.chart.setPeriodLevelsPeriod(e.periodLevelsPeriod),e.crosshairMode!==void 0&&this.chart.setCrosshairMode(e.crosshairMode),e.autoScale!==void 0&&this.chart.setAutoScale(e.autoScale),e.scaleMode===void 0?e.logScale!==void 0&&(this.chart.setLogScale(e.logScale),this.settingsState={...this.settingsState,scaleMode:e.logScale?`logarithmic`:`regular`}):(this.chart.setScaleMode(e.scaleMode),this.settingsState={...this.settingsState,logScale:e.scaleMode===`logarithmic`}),e.numberLocale!==void 0&&this.chart.setNumberLocale(e.numberLocale),e.timezone!==void 0&&this.chart.setTimezoneOffset(e.timezone===`local`?null:Number(e.timezone));let t={...this.chart.getTheme()},n=!1;e.candleUpColor!==void 0&&(t.candleUp=e.candleUpColor,n=!0),e.candleDownColor!==void 0&&(t.candleDown=e.candleDownColor,n=!0),e.candleUpWick!==void 0&&(t.candleUpWick=e.candleUpWick,n=!0),e.candleDownWick!==void 0&&(t.candleDownWick=e.candleDownWick,n=!0),e.backgroundColor!==void 0&&(t.background=e.backgroundColor,n=!0),e.gridColor!==void 0&&(t.grid=e.gridColor,n=!0),n&&this.chart.setTheme(t)}resetSettings(){this.settingsState={...u},this.applySettings(this.settingsState)}async connectStream(){if(this.adapter){this.state={...this.state,connectionState:`connecting`,connectionMessage:`Connecting...`},this.updateUI();try{this.chart.disconnectStream(),await this.chart.connect({adapter:this.adapter,symbol:this.state.symbol,timeframe:this.state.timeframe,historyLimit:this.options.historyLimit??500}),this.chart.setWatermark(this.state.symbol.replace(`USDT`,` / USDT`),{fontSize:48,color:this.state.isDark?`rgba(255,255,255,0.03)`:`rgba(0,0,0,0.03)`}),this.applySymbolLayout(this.state.symbol),this.state={...this.state,connectionState:`connected`,connectionMessage:`Live`},this.refetchCompares()}catch(e){this.state={...this.state,connectionState:`error`,connectionMessage:e instanceof Error?e.message:`Connection failed`}}this.updateUI()}}updateUI(){this.toolbar?.update(this.state),this.sidebar?.update(this.state),this.statusBar?.update({connectionState:this.state.connectionState,message:this.state.connectionMessage,symbol:this.state.symbol,timeframe:this.state.timeframe})}resolveIsDark(e){return e===void 0||e===`dark`?!0:e===`light`?!1:typeof e==`object`&&e.background?this.isColorDark(e.background):!0}resolveTheme(e){return e===void 0||e===`dark`?t.DARK_THEME:e===`light`?t.LIGHT_THEME:typeof e==`object`?e:t.DARK_THEME}isColorDark(e){if(e.startsWith(`#`)&&e.length>=7){let t=parseInt(e.slice(1,3),16),n=parseInt(e.slice(3,5),16),r=parseInt(e.slice(5,7),16);return t+n+r<384}return!0}};exports.ChartWidget=Fe;
1456
2388
  //# sourceMappingURL=index.cjs.map